Compare commits

...

2 Commits

Author SHA1 Message Date
Heng Li
36bfb02298 r257: dropped contained unitigs 2020-06-08 15:43:21 -04:00
Heng Li
afa93e4bbb prepare for further changes 2020-06-06 21:55:41 -04:00
16 changed files with 554 additions and 466 deletions

View File

@@ -10,6 +10,7 @@
#include "Correct.h"
#include "htab.h"
#include "kthread.h"
#include "utils.h"
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);

View File

@@ -19,6 +19,7 @@ static ko_longopt_t long_options[] = {
{ "max-od-final", ko_no_argument, 306 },
{ "ex-list", ko_required_argument, 307 },
{ "ex-iter", ko_required_argument, 308 },
{ "keep-contained",ko_no_argument, 309 },
{ 0, 0, 0 }
};
@@ -404,6 +405,7 @@ int CommandLine_process(int argc, char *argv[], hifiasm_opt_t* asm_opt)
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->flag |= HA_F_KEEP_CONTAINED;
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);

View File

@@ -3,7 +3,7 @@
#include <pthread.h>
#define HA_VERSION "0.7-dirty-r255"
#define HA_VERSION "0.7-dirty-r257"
#define VERBOSE 0
@@ -15,6 +15,7 @@
#define HA_F_SKIP_TRIOBIN 0x20
#define HA_F_PURGE_CONTAIN 0x40
#define HA_F_PURGE_JOIN 0x80
#define HA_F_KEEP_CONTAINED 0x100
#define HA_MIN_OV_DIFF 0.02 // min sequence divergence in an overlap

View File

@@ -4,6 +4,7 @@
#include <pthread.h>
#include "Hash_Table.h"
#include "ksort.h"
#include "utils.h"
pthread_mutex_t output_mutex;
#define overlap_region_key(a) ((a).y_id)

View File

@@ -4,7 +4,7 @@ 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
htab.o hist.o sketch.o anchor.o extract.o overlap2.o sys.o
EXE= hifiasm
LIBS= -lz -lpthread -lm
@@ -34,17 +34,17 @@ depend:
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
Assembly.o: kthread.h utils.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
Hash_Table.o: Hash_Table.h htab.h Process_Read.h Overlaps.h kvec.h kdq.h
Hash_Table.o: CommandLines.h ksort.h
Hash_Table.o: CommandLines.h ksort.h utils.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
Overlaps.o: Purge_Dups.h utils.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
@@ -52,16 +52,17 @@ 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
Trio.o: khashl.h kthread.h kseq.h Process_Read.h Overlaps.h kvec.h kdq.h
Trio.o: CommandLines.h htab.h
Trio.o: CommandLines.h htab.h utils.h
anchor.o: htab.h Process_Read.h Overlaps.h kvec.h kdq.h CommandLines.h
anchor.o: ksort.h Hash_Table.h
anchor.o: ksort.h utils.h Hash_Table.h
extract.o: Process_Read.h Overlaps.h kvec.h kdq.h CommandLines.h khashl.h
extract.o: kseq.h
extract.o: kseq.h utils.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
htab.o: kvec.h kdq.h CommandLines.h utils.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
main.o: Levenshtein_distance.h utils.h
overlap2.o: utils.h CommandLines.h Overlaps.h kvec.h kdq.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
sys.o: utils.h

View File

@@ -9,6 +9,7 @@
#include "Hash_Table.h"
#include "Correct.h"
#include "Purge_Dups.h"
#include "utils.h"
uint32_t debug_purge_dup = 0;
@@ -76,21 +77,17 @@ 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->contain); free(g->con_idx);
free(g->F_seq);
}
free(g);
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)
@@ -132,8 +129,7 @@ void remove_overlaps(ma_hit_t_alloc* source_paf, uint64_t* source_index, long lo
}
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)
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;
@@ -186,7 +182,6 @@ uint64_t *asg_arc_index_core(size_t max_seq, size_t n, const asg_arc_t *a)
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)
@@ -196,7 +191,6 @@ uint64_t *asg_arc_index_core(size_t max_seq, size_t n, const asg_arc_t *a)
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;
}
@@ -276,16 +270,15 @@ void asg_cleanup(asg_t *g)
qns direction of overlap length of this node (not overlap length)
**/
asg_arc_sort(g);
asg_con_sort(g);
g->is_srt = 1;
}
///index the overlaps in graph with query id
if (g->idx == 0) asg_arc_index(g);
if (g->con_idx == 0 && g->n_con > 0) asg_con_index(g);
}
// delete multi-arcs
/**
* remove edges like: v has two out-edges to w
@@ -872,51 +865,6 @@ void drop_edges_by_trio(ma_hit_t_alloc* sources, long long num_sources)
}
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)
{
@@ -1027,108 +975,6 @@ int max_hang, int min_ovlp, uint32_t qn)
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);
// if(delete_all_edges_carefully(sources, coverage_cut, max_hang, min_ovlp,
// Get_qn(*h))==0)
// {
// set_R_to_U(ruIndex, Get_qn(*h), Get_tn(*h), 0);
// }
// sq->del = 1;
// set_R_to_U(ruIndex, Get_qn(*h), Get_tn(*h), 0);
}
else 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);
// if(delete_all_edges_carefully(sources, coverage_cut, max_hang,
// min_ovlp, Get_tn(*h)) == 0)
// {
// set_R_to_U(ruIndex, Get_tn(*h), Get_qn(*h), 0);
// no_fully_tn_num++;
// }
// st->del = 1;
// set_R_to_U(ruIndex, Get_tn(*h), Get_qn(*h), 0);
}
}
}
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();
@@ -1694,9 +1540,7 @@ void print_overlaps(ma_hit_t_alloc* paf, long long rLen, long long interval_s, l
}
void detect_chimeric_reads(ma_hit_t_alloc* paf, long long n_read, uint64_t* readLen,
ma_sub_t* coverage_cut, float shift_rate)
void detect_chimeric_reads(ma_hit_t_alloc* paf, long long n_read, uint64_t* readLen, ma_sub_t* coverage_cut, float shift_rate)
{
double startTime = Get_T();
init_aux_table();
@@ -2108,71 +1952,6 @@ static inline int asg_is_single_edge(const asg_t *g, uint32_t v, uint32_t start_
}
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;
}
@@ -4484,143 +4263,6 @@ int asg_arc_del_cross_bubble(asg_t *g, long long max_dist)
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;
}
///max_ext is 4
int asg_cut_tip(asg_t *g, int max_ext)
{
@@ -26086,13 +25728,12 @@ int max_hang, int min_ovlp)
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, int debug_g)
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, int debug_g)
{
ma_sub_t *coverage_cut = *coverage_cut_ptr;
asg_t *sg = *sg_ptr;
@@ -26330,52 +25971,50 @@ ma_sub_t **coverage_cut_ptr, int debug_g)
*sg_ptr = sg;
}
void build_string_graph_without_clean(
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, int write)
void build_string_graph_without_clean(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, int write)
{
R_to_U ruIndex;
init_R_to_U(&ruIndex, n_read);
asg_t *sg = NULL;
ma_sub_t* coverage_cut = NULL;
R_to_U ruIndex;
init_R_to_U(&ruIndex, n_read);
asg_t *sg = NULL;
ma_sub_t* coverage_cut = NULL;
// debug_info_of_specfic_read("m64011_190329_072846/80545633/ccs", sources, reverse_sources, -1, "clean");
///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;
// debug_info_of_specfic_read("m64011_190329_072846/80545633/ccs", sources, reverse_sources, -1, "clean");
if (asm_opt.flag & HA_F_VERBOSE_GFA)
{
if(load_debug_graph(&sg, &sources, &coverage_cut, output_file_name, &reverse_sources, &ruIndex))
{
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, 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);
}
///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;
try_rescue_overlaps(sources, reverse_sources, n_read, 4);
if (asm_opt.flag & HA_F_VERBOSE_GFA)
{
if (load_debug_graph(&sg, &sources, &coverage_cut, output_file_name, &reverse_sources, &ruIndex))
{
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, 0);
asg_destroy(sg);
free(coverage_cut);
destory_R_to_U(&ruIndex);
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, 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);
}
try_rescue_overlaps(sources, reverse_sources, n_read, 4);
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, 0);
asg_destroy(sg);
free(coverage_cut);
destory_R_to_U(&ruIndex);
}

View File

@@ -103,7 +103,6 @@ typedef struct {
uint8_t no_l_indel;
} 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
@@ -112,11 +111,10 @@ typedef struct {
char *s; // unitig sequence is not null
} ma_utg_t;
typedef struct {
uint32_t len:31, del:1;
uint8_t c;
uint8_t weak_contain;
} asg_seq_t;
typedef struct {
@@ -128,6 +126,10 @@ typedef struct {
asg_seq_t *seq;
uint64_t *idx;
uint32_t m_con, n_con;
uint64_t *contain;
uint64_t *con_idx;
uint8_t* seq_vis;
uint32_t n_F_seq;
@@ -505,6 +507,25 @@ void init_Edge_iter(asg_t* g, uint32_t v, asg_arc_t* new_edges, uint32_t new_edg
int get_arc_t(Edge_iter* x, asg_arc_t* get);
int asg_pop_bubble_primary_trio(ma_ug_t *ug, int max_dist, uint32_t positive_flag, uint32_t negative_flag);
/*************************************
* Routines modified for containment *
*************************************/
void delete_single_edge(ma_hit_t_alloc *sources, const ma_sub_t *coverage_cut, uint32_t qn, uint32_t tn);
void delete_all_edges(ma_hit_t_alloc *sources, ma_sub_t *coverage_cut, uint32_t qn);
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 asg_con_sort(asg_t *g);
void asg_con_index(asg_t *g);
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);
int asg_arc_del_trans(asg_t *g, int fuzz);
int asg_drop_contained_utg(asg_t *g);
#define asg_con_n(g, v) ((g)->contain? (uint32_t)(g)->con_idx[(v)] : 0)
#define asg_con_a(g, v) ((g)->contain? &(g)->contain[(g)->con_idx[(v)]>>32] : 0)
/*******************
* Other rountines *
*******************/
inline int get_real_length(asg_t *g, uint32_t v, uint32_t* v_s)
{

View File

@@ -9,6 +9,7 @@
#include "kseq.h"
#include "Process_Read.h"
#include "htab.h"
#include "utils.h"
#include "CommandLines.h"
#define YAK_MAX_KMER 31

View File

@@ -1,6 +1,7 @@
#include <stdio.h>
#include "htab.h"
#include "ksort.h"
#include "utils.h"
#include "Hash_Table.h"
#define HA_KMER_GOOD_RATIO 0.333

View File

@@ -3,21 +3,19 @@
#include "Process_Read.h"
#include "khashl.h"
#include "kseq.h"
#include "utils.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);
MALLOC(dst, len + 1);
memcpy(dst, src, len + 1);
return dst;
}
@@ -25,7 +23,7 @@ char *gfa_strdup(const char *src)
char *gfa_strndup(const char *src, size_t n)
{
char *dst;
GFA_MALLOC(dst, n + 1);
MALLOC(dst, n + 1);
strncpy(dst, src, n);
dst[n] = 0;
return dst;
@@ -42,7 +40,7 @@ char **gv_read_list(const char *o, int *n_)
if (*p == ',' || *p == 0) {
if (n == m) {
m = m? m<<1 : 16;
GFA_REALLOC(s, m);
REALLOC(s, m);
}
s[n++] = gfa_strndup(q, p - q);
if (*p == 0) break;
@@ -63,7 +61,7 @@ char **gv_read_list(const char *o, int *n_)
for (p = str.s; *p && !isspace(*p); ++p);
if (n == m) {
m = m? m<<1 : 16;
GFA_REALLOC(s, m);
REALLOC(s, m);
}
s[n++] = gfa_strndup(str.s, p - str.s);
}
@@ -94,7 +92,7 @@ void ha_extract_print(const All_reads *rs, int n_rounds, int n, char **list)
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);
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));

View File

@@ -9,6 +9,7 @@
#include "kseq.h"
#include "ksort.h"
#include "htab.h"
#include "utils.h"
#define YAK_COUNTER_BITS 12
#define YAK_N_COUNTS (1<<YAK_COUNTER_BITS)

19
htab.h
View File

@@ -38,13 +38,6 @@ 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);
double yak_cputime(void);
void yak_reset_realtime(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);
void ha_sketch(const char *str, int len, int w, int k, uint32_t rid, int is_hpc, ha_mz1_v *p, const void *hf);
@@ -80,18 +73,6 @@ static inline uint64_t yak_hash_long(uint64_t x[4])
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))))
#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__))

View File

@@ -4,7 +4,7 @@
#include "Process_Read.h"
#include "Assembly.h"
#include "Levenshtein_distance.h"
#include "htab.h"
#include "utils.h"
int main(int argc, char *argv[])
{

407
overlap2.cpp Normal file
View File

@@ -0,0 +1,407 @@
#include <assert.h>
#include "utils.h"
#include "CommandLines.h"
#include "Overlaps.h"
#include "Process_Read.h"
/*******************************
* Dropping strong containment *
*******************************/
static ma_hit_t *get_specific_overlap_with_del(ma_hit_t_alloc *sources, const ma_sub_t *coverage_cut, uint32_t qn, uint32_t tn)
{
if (coverage_cut[qn].del || coverage_cut[tn].del) return NULL;
ma_hit_t_alloc *x = &sources[qn];
uint32_t i;
for (i = 0; i < x->length; i++) {
if (x->buffer[i].del) continue;
if (coverage_cut[Get_qn(x->buffer[i])].del) continue;
if (coverage_cut[Get_tn(x->buffer[i])].del) continue;
if (Get_tn(x->buffer[i]) == tn && Get_qn(x->buffer[i]) == qn)
return &x->buffer[i];
}
return NULL;
}
void delete_single_edge(ma_hit_t_alloc *sources, const ma_sub_t *coverage_cut, uint32_t qn, uint32_t tn)
{
ma_hit_t *tmp = get_specific_overlap_with_del(sources, coverage_cut, qn, tn);
if (tmp != NULL) tmp->del = 1;
}
void delete_all_edges(ma_hit_t_alloc *sources, ma_sub_t *coverage_cut, uint32_t qn)
{
ma_hit_t_alloc* x = &sources[qn];
uint32_t i;
for (i = 0; i < x->length; i++) {
x->buffer[i].del = 1;
delete_single_edge(sources, coverage_cut, Get_tn(x->buffer[i]), Get_qn(x->buffer[i]));
}
coverage_cut[qn].del = 1;
}
void ma_hit_contained_advance(ma_hit_t_alloc *sources, long long n_read, ma_sub_t *coverage_cut, R_to_U *ruIndex, int max_hang, int min_ovlp)
{
int32_t r;
long long i, j, n_strong_contain = 0, n_weak_contain = 0;
asg_arc_t t;
ma_hit_t *h = NULL;
ma_sub_t *sq = NULL;
ma_sub_t *st = NULL;
for (i = 0; i < n_read; ++i) {
if (coverage_cut[i].del) continue;
for (j = 0; j < (long long)sources[i].length; j++) {
h = &sources[i].buffer[j];
//check the corresponding two reads
sq = &coverage_cut[Get_qn(*h)];
st = &coverage_cut[Get_tn(*h)];
/****************************may have trio bugs********************************/
if (sq->del || st->del) continue;
if (h->del) continue;
/****************************may have trio bugs********************************/
r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, asm_opt.max_hang_rate, min_ovlp, &t);
//assert(r != MA_HT_INT && r != MA_HT_SHORT_OVLP);
if (r == MA_HT_QCONT) {
if (h->ml || (asm_opt.flag & HA_F_KEEP_CONTAINED) == 0) {
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);
// if (delete_all_edges_carefully(sources, coverage_cut, max_hang, min_ovlp, Get_qn(*h)) == 0)
// set_R_to_U(ruIndex, Get_qn(*h), Get_tn(*h), 0);
// sq->del = 1;
// set_R_to_U(ruIndex, Get_qn(*h), Get_tn(*h), 0);
}
if (h->ml) ++n_strong_contain;
else ++n_weak_contain;
} else if (r == MA_HT_TCONT) {
if (h->ml || (asm_opt.flag & HA_F_KEEP_CONTAINED) == 0) {
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);
// if (delete_all_edges_carefully(sources, coverage_cut, max_hang, min_ovlp, Get_tn(*h)) == 0)
// set_R_to_U(ruIndex, Get_tn(*h), Get_qn(*h), 0);
// st->del = 1;
// set_R_to_U(ruIndex, Get_tn(*h), Get_qn(*h), 0);
}
if (h->ml) ++n_strong_contain;
else ++n_weak_contain;
}
}
}
transfor_R_to_U(ruIndex);
for (i = 0; i < n_read; ++i) {
int m = 0;
for (j = 0; j < (long long)sources[i].length; j++) {
ma_hit_t *h = &(sources[i].buffer[j]);
if (h->del) continue;
/// both the qn and tn have not been deleted
if (coverage_cut[Get_qn(*h)].del != 1 && coverage_cut[Get_tn(*h)].del != 1)
h->del = 0, ++m;
else h->del = 1;
}
/// sources[i].length == 0 means all overlapped reads with read i are the contained reads
if (m == 0) coverage_cut[i].del = 1;
}
fprintf(stderr, "[M::%s] %lld strong containments; %lld weak containments\n", __func__,
n_strong_contain, n_weak_contain);
}
/************************************
* Graph construction and reduction *
************************************/
static inline void asg_con_push(asg_t *g, uint32_t lower, uint32_t upper, int rev)
{
if (g->n_con == g->m_con) {
g->m_con = g->m_con? g->m_con<<1 : 16;
REALLOC(g->contain, g->m_con);
}
g->contain[g->n_con++] = (uint64_t)lower << 32 | upper << 1 | (!!rev);
}
void asg_con_sort(asg_t *g)
{
if (g->n_con > 1) radix_sort_ha64(g->contain, g->contain + g->n_con);
}
void asg_con_index(asg_t *g)
{
uint32_t i, k;
if (g->n_con == 0 || g->contain == 0) return;
if (g->con_idx) free(g->con_idx);
CALLOC(g->con_idx, g->n_seq);
for (k = 0, i = 1; i < g->n_con; ++i)
if (g->contain[k] != g->contain[i])
g->contain[k++] = g->contain[i];
g->n_con = k;
for (i = 1, k = 0; i <= g->n_con; ++i)
if (i == g->n_con || g->contain[i-1]>>32 != g->contain[i]>>32)
g->con_idx[g->contain[i-1]>>32] = (uint64_t)k << 32 | (i - k), k = i;
}
asg_t *ma_sg_gen(const ma_hit_t_alloc* sources, long long n_read, const ma_sub_t *coverage_cut, int max_hang, int min_ovlp)
{
size_t i, j;
asg_t *g;
g = asg_init();
// add seq to graph, seq just save the length of each read
for (i = 0; i < (uint64_t)n_read; ++i) {
///if a read has been deleted, should we still add them?
asg_seq_set(g, i, coverage_cut[i].e - coverage_cut[i].s, coverage_cut[i].del);
g->seq[i].c = coverage_cut[i].c;
}
g->seq_vis = (uint8_t*)calloc(g->n_seq*2, sizeof(uint8_t));
for (i = 0; i < (uint64_t)n_read; ++i) {
for (j = 0; j < sources[i].length; ++j) {
int r, ql, tl;
asg_arc_t t, *p;
const ma_hit_t *h = &sources[i].buffer[j];
uint32_t qn, tn;
if (h->del) continue;
qn = Get_qn(*h);
tn = Get_tn(*h);
ql = coverage_cut[qn].e - coverage_cut[qn].s;
tl = coverage_cut[tn].e - coverage_cut[tn].s;
r = ma_hit2arc(h, ql, tl, max_hang, asm_opt.max_hang_rate, min_ovlp, &t);
if (r >= 0) {
p = asg_arc_pushp(g);
*p = t;
} else if (r == MA_HT_QCONT) {
assert(h->ml == 0);
asg_con_push(g, h->qns>>32, h->tn, h->rev);
} else if (r == MA_HT_TCONT) {
assert(h->ml == 0);
asg_con_push(g, h->tn, h->qns>>32, h->rev);
}
}
}
asg_cleanup(g);
g->r_seq = g->n_seq;
return g;
}
typedef struct {
uint32_t len;
uint8_t mark; // can only be 0, 1 or 2
} trinfo_t;
// transitive reduction; see Myers, 2005
int asg_arc_del_trans(asg_t *g, int fuzz)
{
trinfo_t *info;
///n_vtx = number of seq * 2; the reason is that each read has two direction (query->target, target->query)
uint32_t v, n_vtx = g->n_seq * 2, n_reduced = 0;
///at first, all nodes should be set to vacant
CALLOC(info, n_vtx);
/**v is the id+direction of a node,
* the high 31-bit is the id,
* and the lowest 1-bit is the direction
* (0 means query-to-target, 1 means target-to-query)**/
for (v = 0; v < n_vtx; ++v) {
///nv is the number of overlaps with v(qn+direction)
uint32_t L, i, nv = asg_arc_n(g, v);
///av is the array of v
asg_arc_t *av = asg_arc_a(g, v);
///that means in this direction, read v is not overlapped with any other reads
if (nv == 0) continue; // no hits
// if the read itself has been removed
if (g->seq[v>>1].del) {
for (i = 0; i < nv; ++i) av[i].del = 1, ++n_reduced;
continue;
}
/**
********************************query-to-target overlap****************************
case 1: u = 0, rev = 0 in the view of target: direction is 1
query: CCCCCCCCTAATTAAAAT target: TAATTAAAATGGGGGG (use ex-target as query)
|||||||||| <---> ||||||||||
target: TAATTAAAATGGGGGG query: CCCCCCCCTAATTAAAAT (use ex-query as target)
case 2: u = 0, rev = 1 in the view of target: direction is 0
query: CCCCCCCCTAATTAAAAT target: CCCCCCATTTTAATTA (use ex-target as query)
|||||||||| <---> ||||||||||
target: TAATTAAAATGGGGGG query: ATTTTAATTAGGGGGGGG (use ex-query as target)
********************************query-to-target overlap****************************
********************************target-to-query overlap****************************
case 3: u = 1, rev = 0 in the view of target: direction is 0
query: AAATAATATCCCCCCGCG target: GGGCCGGCAAATAATAT (use ex-target as query)
||||||||| <---> |||||||||
target: GGGCCGGCAAATAATAT query: AAATAATATCCCCCCGCG (use ex-query as target)
case 4: u = 1, rev = 1 in the view of target: direction is 1
query: AAATAATATCCCCCCGCG target: ATATTATTTGCCGGCCC (use ex-target as query)
||||||||| <---> |||||||||
target: GGGCCGGCAAATAATAT query: CGCGGGGGATATTATTT (use ex-query as target)
********************************target-to-query overlap****************************
p->ul: |____________31__________|__________1___________|______________32_____________|
qns direction of overlap length of this node (not overlap length)
(in the view of query)
p->v : |___________31___________|__________1___________|
tns reverse direction of overlap
(in the view of target)
p->ol: overlap length
**/
// all outnode of v should be set to "not reduce"
for (i = 0; i < nv; ++i) {
uint32_t w = av[i].v;
info[w].mark = g->seq[w>>1].del? 2 : 1;
//if (asg_con_n(g, w>>1) > 0) info[w].mark = 2;
info[w].len = asg_arc_len(av[i]);
}
// remove contained reads
for (i = 0; i < nv; ++i) {
uint32_t j, nw, w = av[i].v;
uint64_t *aw;
if (info[w].mark != 1) continue;
nw = asg_con_n(g, w>>1);
if (nw == 0) continue;
aw = asg_con_a(g, w>>1);
for (j = 0; j < nw; ++j) {
uint32_t x = (uint32_t)aw[j];
if (w&1) x ^= 1;
if (info[x].mark == 1 && info[x].len <= info[w].len)
break;
}
if (j < nw) info[w].mark = 2;
//if (nw > 0) fprintf(stderr, "X\t%.*s\t%.*s\n", (int)Get_NAME_LENGTH(R_INF, w>>1), Get_NAME(R_INF, w>>1), (int)Get_NAME_LENGTH(R_INF, (uint32_t)aw[j]>>1), Get_NAME(R_INF, (uint32_t)aw[j]>>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) {
uint32_t w = av[i].v;
uint32_t j, nw = asg_arc_n(g, w);
uint32_t is_con = (asg_con_n(g, w>>1) > 0);
asg_arc_t *aw = asg_arc_a(g, w);
if (info[w].mark != 1) continue;
for (j = 0; j < nw; ++j) {
uint32_t x, sum = asg_arc_len(aw[j]) + asg_arc_len(av[i]);
if (sum > L) break;
x = aw[j].v;
if (info[x].mark == 1 && sum < info[x].len + fuzz && sum + fuzz > info[x].len) {
if (!is_con || asg_con_n(g, x>>1) > 0)
info[x].mark = 2;
}
}
}
#if 0
for (i = 0; i < nv; ++i) {
uint32_t w = av[i].v;
uint32_t j, nw = asg_arc_n(g, w);
asg_arc_t *aw = asg_arc_a(g, w);
for (j = 0; j < nw && (j == 0 || asg_arc_len(aw[j]) < fuzz); ++j)
if (info[aw[j].v].mark) info[aw[j].v].mark = 2;
}
#endif
// remove edges
for (i = 0; i < nv; ++i) {
if (info[av[i].v].mark == 2) av[i].del = 1, ++n_reduced;
info[av[i].v].mark = 0;
}
}
free(info);
if (n_reduced) {
asg_cleanup(g);
asg_symm(g);
asg_drop_contained_utg(g);
}
fprintf(stderr, "[M::%s] transitively reduced %d arcs\n", __func__, n_reduced);
return n_reduced;
}
#define GFA_VT_MERGEABLE 0
#define GFA_VT_TIP 1
#define GFA_VT_MULTI_OUT 2
#define GFA_VT_MULTI_IN 3
static inline int32_t gfa_deg(const asg_t *g, uint32_t v, uint32_t *w)
{
uint32_t i, nv, nv0, k;
const asg_arc_t *av;
if (w) *w = (uint32_t)-1;
if (g->seq[v>>1].del) return 0;
nv0 = k = asg_arc_n(g, v);
av = asg_arc_a(g, v);
for (i = nv = 0; i < nv0; ++i)
if (!av[i].del)
++nv, k = i;
if (w) *w = nv == 1? av[k].v : (uint32_t)-1;
return nv;
}
static inline int32_t gfa_vtype(const asg_t *g, uint32_t v, uint32_t *w_)
{
int32_t nv, nw;
uint32_t w;
nv = gfa_deg(g, v, &w);
if (w_) *w_ = w;
if (nv == 0) return GFA_VT_TIP;
if (nv > 1) return GFA_VT_MULTI_OUT;
nw = gfa_deg(g, w^1, 0);
return nw == 1? GFA_VT_MERGEABLE : GFA_VT_MULTI_IN;
}
int asg_drop_contained_utg(asg_t *g)
{
uint32_t n_vtx = g->n_seq * 2, v, cnt = 0;
if (g->contain == 0) return 0;
for (v = 0; v < n_vtx; ++v) {
int32_t vt, is_contained;
uint32_t w;
if (g->seq[v>>1].del) continue;
if (asg_con_n(g, v>>1) == 0) continue;
vt = gfa_vtype(g, v^1, &w);
if (vt == GFA_VT_MERGEABLE) continue;
w = v, is_contained = 1;
while (1) {
if (asg_con_n(g, w>>1) == 0) {
is_contained = 0;
break;
}
vt = gfa_vtype(g, w, &w);
if (vt != GFA_VT_MERGEABLE) break;
}
if (is_contained) {
w = v;
while (1) {
++cnt;
asg_seq_del(g, w>>1);
vt = gfa_vtype(g, w, &w);
if (vt != GFA_VT_MERGEABLE) break;
}
}
}
if (cnt > 0) asg_cleanup(g);
fprintf(stderr, "[M::%s] drop %d reads in contained unitigs\n", __func__, cnt);
return cnt;
}

View File

@@ -1,6 +1,6 @@
#include <sys/resource.h>
#include <sys/time.h>
#include "htab.h"
#include "utils.h"
int yak_verbose = 3;

33
utils.h Normal file
View File

@@ -0,0 +1,33 @@
#ifndef HA_UTILS_H
#define HA_UTILS_H
#include <stdint.h>
#ifndef MALLOC
#define MALLOC(ptr, len) ((ptr) = (__typeof__(ptr))malloc((len) * sizeof(*(ptr))))
#endif
#ifndef CALLOC
#define CALLOC(ptr, len) ((ptr) = (__typeof__(ptr))calloc((len), sizeof(*(ptr))))
#endif
#ifndef REALLOC
#define REALLOC(ptr, len) ((ptr) = (__typeof__(ptr))realloc((ptr), (len) * sizeof(*(ptr))))
#endif
#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
void radix_sort_ha64(uint64_t *st, uint64_t *en);
double yak_cputime(void);
void yak_reset_realtime(void);
double yak_realtime(void);
long yak_peakrss(void);
double yak_peakrss_in_gb(void);
double yak_cpu_usage(void);
#endif