static void test_walk(GraphWalker *gwlk, RepeatWalker *rptwlk, dBNode node0, dBNodeBuffer *nbuf, const dBGraph *graph, size_t expnkmers, const char *ans) { db_node_buf_reset(nbuf); graph_walker_init(gwlk, graph, 0, 0, node0); do { db_node_buf_add(nbuf, gwlk->node); } while(graph_walker_next(gwlk) && rpt_walker_attempt_traverse(rptwlk, gwlk)); // db_nodes_print(nbuf->data, nbuf->len, graph, stdout); // printf("\n"); // printf("%s\n", graph_step_str[gwlk->last_step.status]); TASSERT2(nbuf->len == expnkmers, "%zu / %zu", nbuf->len, expnkmers); char tmp[nbuf->len+MAX_KMER_SIZE]; db_nodes_to_str(nbuf->data, nbuf->len, graph, tmp); TASSERT2(strcmp(tmp,ans) == 0, "%s vs %s", tmp, ans); graph_walker_finish(gwlk); rpt_walker_fast_clear(rptwlk, nbuf->data, nbuf->len); }
// `node1` should be the first node of a supernode // `node0` should be the previous node // `next_base` is the last base of `node1` // `jmpfunc` is called with each supernode traversed and if it returns true // we continue crawling, otherwise we stop // `endfunc` is a function called at the end of traversal void graph_crawler_fetch(GraphCrawler *crawler, dBNode node0, dBNode next_nodes[4], size_t take_idx, size_t num_next, uint32_t *cols, size_t ncols, bool (*jmpfunc)(GraphCache *_cache, GCacheStep *_step, void *_arg), void (*endfunc)(GraphCache *_cache, uint32_t _pathid, void *_arg), void *arg) { const dBGraph *db_graph = crawler->cache.db_graph; GraphCache *cache = &crawler->cache; GraphWalker *wlk = &crawler->wlk; RepeatWalker *rptwlk = &crawler->rptwlk; GCUniColPath *unipaths = crawler->unicol_paths; ctx_assert(take_idx < num_next); ctx_assert(!db_nodes_are_equal(node0, next_nodes[take_idx])); // Fetch all paths in all colours dBNode node1 = next_nodes[take_idx]; bool is_fork; size_t i, c, col, nedges_cols, num_unicol_paths = 0; int pathid; for(c = 0; c < ncols; c++) { col = (cols != NULL ? cols[c] : c); if(db_node_has_col(db_graph, node0.key, col) && db_node_has_col(db_graph, node1.key, col)) { // Determine if this fork is a fork in the current colour for(nedges_cols = 0, i = 0; i < num_next && nedges_cols <= 1; i++) nedges_cols += db_node_has_col(db_graph, next_nodes[i].key, col); is_fork = (nedges_cols > 1); graph_walker_setup(wlk, true, col, col, db_graph); graph_walker_start(wlk, node0); graph_walker_force(wlk, node1, is_fork); pathid = graph_crawler_load_path(cache, node1, wlk, rptwlk, jmpfunc, arg); if(endfunc != NULL) endfunc(cache, pathid, arg); graph_walker_finish(wlk); graph_crawler_reset_rpt_walker(rptwlk, cache, pathid); unipaths[num_unicol_paths++] = (GCUniColPath){.colour = col, .pathid = pathid}; } else pathid = -1; crawler->col_paths[col] = pathid; }
// `fork_node` is a node with outdegree > 1 void find_bubbles(BubbleCaller *caller, dBNode fork_node) { graph_cache_reset(&caller->cache); const dBGraph *db_graph = caller->db_graph; GraphCache *cache = &caller->cache; GraphWalker *wlk = &caller->wlk; RepeatWalker *rptwlk = &caller->rptwlk; // char tmpstr[MAX_KMER_SIZE+3]; // db_node_to_str(db_graph, fork_node, tmpstr); // status("Calling from %s", tmpstr); dBNode nodes[4]; Nucleotide bases[4]; size_t i, num_next, num_edges_in_col; BinaryKmer fork_bkmer = db_node_get_bkmer(db_graph, fork_node.key); num_next = db_graph_next_nodes(db_graph, fork_bkmer, fork_node.orient, db_node_edges(db_graph, fork_node.key, 0), nodes, bases); // loop over alleles, then colours Colour colour, colours_loaded = db_graph->num_of_cols; bool node_has_col[4]; uint32_t pathid; for(colour = 0; colour < colours_loaded; colour++) { if(!db_node_has_col(db_graph, fork_node.key, colour)) continue; // Determine if this fork is a fork in the current colour num_edges_in_col = 0; for(i = 0; i < num_next; i++) { node_has_col[i] = (db_node_has_col(db_graph, nodes[i].key, colour) > 0); num_edges_in_col += node_has_col[i]; } graph_walker_setup(wlk, true, colour, colour, db_graph); for(i = 0; i < num_next; i++) { if(node_has_col[i]) { graph_walker_start(wlk, fork_node); graph_walker_force(wlk, nodes[i], num_edges_in_col > 1); pathid = graph_crawler_load_path_limit(cache, nodes[i], wlk, rptwlk, caller->prefs.max_allele_len); graph_walker_finish(wlk); graph_crawler_reset_rpt_walker(rptwlk, cache, pathid); } } } // Set up 5p flank caller->flank5p.b[0] = db_node_reverse(fork_node); caller->flank5p.len = 0; // set to one to signify we haven't fetched flank yet }
static inline void reset(GraphWalker *wlk, RepeatWalker *rptwlk, const dBNodeBuffer *nbuf) { graph_walker_finish(wlk); rpt_walker_fast_clear(rptwlk, nbuf->b, nbuf->len); }