static inline KOccurRun* fetch_ref_contact(const GraphCache *cache, uint32_t pathid, const PathRefRun *ref_runs, KOccurRunBuffer *runbuf) { // Get path const GCachePath *path = graph_cache_path(cache, pathid); const GCacheStep *steps = graph_cache_step(cache, path->first_step); size_t num_steps = path->num_steps; // Get runs along the ref PathRefRun ref_run = ref_runs[pathid]; size_t num_runs = ref_run.num_runs; KOccurRun *koruns = runbuf->data + ref_run.first_runid; koruns_sort_by_qoffset(koruns, num_runs); // Set qoffset to be the kmer offset in the path size_t r, s, offset = 0; for(s = r = 0; s < num_steps; s++) { for(; r < num_runs && koruns[r].qoffset == s; r++) { koruns[r].qoffset = offset; } if(r == num_runs) break; const GCacheSnode *snode = graph_cache_snode(cache, steps[s].supernode); offset += snode->num_nodes; } return koruns; }
// Load GCacheSteps into caller->spp_forward (if they traverse the snode forward) // or caller->spp_reverse (if they traverse the snode in reverse) void find_bubbles_ending_with(BubbleCaller *caller, GCacheSnode *snode) { // possible 3p flank (i.e. bubble end) // record paths that go through here forwards, and in reverse cache_stepptr_buf_reset(&caller->spp_forward); cache_stepptr_buf_reset(&caller->spp_reverse); uint32_t stepid = snode->first_step; GCacheStep *step; while(stepid != UINT32_MAX) { step = graph_cache_step(&caller->cache, stepid); if(step->orient == FORWARD) { cache_stepptr_buf_push(&caller->spp_forward, &step, 1); } else { cache_stepptr_buf_push(&caller->spp_reverse, &step, 1); } stepid = step->next_step; } // Filter out non-bubbles remove_non_bubbles(caller, &caller->spp_forward); remove_non_bubbles(caller, &caller->spp_reverse); }
// For 5p flank only pick up new runs starting at the first supernode static bool gcrawler_flank5p_stop_at_ref_covg(GraphCache *cache, GCacheStep *step, void *arg) { BreakpointCaller *caller = (BreakpointCaller*)arg; const GCachePath *path = graph_cache_path(cache, step->pathid); const GCacheStep *first_step = graph_cache_step(cache, path->first_step); bool pickup_new_runs = (step == first_step); return gcrawler_stop_at_ref_covg(cache, step, caller, &caller->koruns_5p, &caller->koruns_5p_ended, pickup_new_runs) && (caller->koruns_5p.len > 0); }
// Constructs a path of supernodes (SupernodePath) // `wlk` GraphWalker should be set to go at `node` // `rptwlk` RepeatWalker should be clear // `jmpfunc` is called with each supernode traversed and if it returns true // we continue crawling, otherwise we stop. If NULL assume always true // returns pathid in GraphCache uint32_t graph_crawler_load_path(GraphCache *cache, dBNode node, GraphWalker *wlk, RepeatWalker *rptwlk, bool (*jmpfunc)(GraphCache *_cache, GCacheStep *_step, void *_arg), void *arg) { size_t i; uint32_t stepid, pathid = graph_cache_new_path(cache); ctx_assert(db_nodes_are_equal(wlk->node, node)); for(i = 0; ; i++) { stepid = graph_cache_new_step(cache, node); GCacheStep *step = graph_cache_step(cache, stepid); GCacheSnode *snode = graph_cache_snode(cache, step->supernode); // Traverse to the end of the supernode walk_supernode_end(cache, snode, step->orient, wlk); if(jmpfunc != NULL && !jmpfunc(cache, step, arg)) break; // Find next node uint8_t num_edges; const dBNode *next_nodes; Nucleotide next_bases[4]; if(step->orient == FORWARD) { num_edges = snode->num_next; next_nodes = snode->next_nodes; binary_seq_unpack_byte(next_bases, snode->next_bases); } else { num_edges = snode->num_prev; next_nodes = snode->prev_nodes; binary_seq_unpack_byte(next_bases, snode->prev_bases); } // Traverse to next supernode if(!graph_walker_next_nodes(wlk, num_edges, next_nodes, next_bases) || !rpt_walker_attempt_traverse(rptwlk, wlk)) break; node = wlk->node; } return pathid; }
void graph_crawler_reset_rpt_walker(RepeatWalker *rptwlk, const GraphCache *cache, uint32_t pathid) { rpt_walker_fast_clear(rptwlk, NULL, 0); const GCachePath *path = graph_cache_path(cache, pathid); const GCacheStep *step = graph_cache_step(cache, path->first_step), *endstep; const GCacheSnode *snode; const dBNode *node0, *node1; // Loop over supernodes in the path for(endstep = step + path->num_steps; step < endstep; step++) { // We don't care about orientation here snode = graph_cache_snode(cache, step->supernode); node0 = graph_cache_first_node(cache, snode); node1 = graph_cache_last_node(cache, snode); rpt_walker_fast_clear_single_node(rptwlk, *node0); rpt_walker_fast_clear_single_node(rptwlk, *node1); } }