/* * Joins contig 'lnconr' to contig 'lnconl' at offset 'relx', producing a * new contig in place of 'lnconl'. * The old 'lnconr' is removed. * * Returns 0 for success, -1 for error (currently never) */ int dojoin(GapIO *io, int lnconl, int lnconr, int relx) { int gl_r = io_crnbr(io, lnconl); int gl_l; int gr_l = io_clnbr(io, lnconr); int i, len, right = 0; f_int tmp; GContigs c; reg_length rl; reg_join rj; /* Shift readings in lnconr by relx */ io_relpos(io, gr_l) = relx+1; i = gr_l; while (i = io_rnbr(io, i)) { io_relpos(io, i) += relx; } /* Linkup ends of contigs (but not yet in correct left to right order) */ io_lnbr(io, gr_l) = gl_r; io_rnbr(io, gl_r) = gr_l; /* Call MERGE() to shuffle the links to the correct order */ tmp = io_dbsize(io) - lnconl; merge_(&io_relpos(io,1), &io_length(io,1), &io_lnbr(io,1), &io_rnbr(io,1), &tmp, &io_dbsize(io)); /* MERGE() doesn't save the readings, so do that ourselves */ for (right = i = io_clnbr(io, lnconl); i; right = i, i = io_rnbr(io, i)) { GReadings r; gel_read(io, i, r); r.left = io_lnbr(io, i); r.right = io_rnbr(io, i); r.position = io_relpos(io, i); gel_write(io, i, r); } /* merge contig annotation lists and update contig length */ merge_contig_tags(io, lnconl, lnconr, relx); /* merge note lists */ merge_contig_notes(io, lnconr, lnconl); contig_read(io, lnconr, c); len = c.length + relx; contig_read(io, lnconl, c); if (c.length < len) c.length = len; c.right = right; contig_write(io, lnconl, c); io_clength(io, lnconl) = c.length; io_crnbr(io, lnconl) = c.right; /* * The order of notifications here is crucial. * * We need to firstly notify the right contig that it's been joined to * the left contig. * * Merge the contig registration lists (copy right into left). * * Then we delete the right contig. Note that this may imply that the * left contig number changes, so we convert to a gel number during the * duration of this call. * * Finally we then tell the left contig that it's length has changed. */ /* Notify right of join */ rj.job = REG_JOIN_TO; rj.contig = lnconl; rj.offset = relx; contig_notify(io, lnconr, (reg_data *)&rj); /* Merge lists */ contig_register_join(io, lnconr, lnconl); /* Delete old contig (lnconr) */ gl_l = io_clnbr(io, lnconl); io_delete_contig(io, lnconr); lnconl = rnumtocnum(io, gl_l); /* Notify left of join */ rl.job = REG_LENGTH; rl.length = c.length; contig_notify(io, lnconl, (reg_data *)&rl); flush2t(io); return 0; }
void update_contig_order(Tcl_Interp *interp, GapIO *io, int cs_id, int *contig_array, int num_contigs, int cx) { GCardinal *order = ArrayBase(GCardinal, io->contig_order); obj_cs *cs; int i, j; double wx, wy; int left_position; char cmd[1024]; int orig_pos = 0; reg_buffer_start rs; reg_buffer_end re; reg_order ro; cs = result_data(io, cs_id, 0); CanvasToWorld(cs->canvas, cx, 0, &wx, &wy); /* * returns the nth contig to the left of the wx, NOT the contig number. * If this is to the left of the first contig, returns 0. */ left_position = find_left_position(io, order, wx); for (i = 0; i < NumContigs(io); i++) { if (order[i] == contig_array[0]) { orig_pos = i+1; break; } } /* convert index on order to index on contig num */ for (i = 0; i < num_contigs; i++) { for (j = 0; j < NumContigs(io); j++) { if (order[j] == contig_array[i]) break; } ReOrder(io, order, j, left_position); if (j > left_position) { left_position++; orig_pos++; } } ro.job = REG_ORDER; ro.pos = left_position; #ifdef HACK /* HACK is there a better way of representing this - only need to * replot once */ contig_notify(io, 1, (reg_data *)&ro); #endif /* Notify of the start of the flurry of updates */ rs.job = REG_BUFFER_START; for (i = 0; i < num_contigs; i++) { contig_notify(io, contig_array[i], (reg_data *)&rs); } ro.job = REG_ORDER; ro.pos = left_position; for (i = 0; i< num_contigs; i++) contig_notify(io, contig_array[i], (reg_data *)&ro); /* Notify the end of our updates */ re.job = REG_BUFFER_END; for (i = 0; i < num_contigs; i++) { contig_notify(io, contig_array[i], (reg_data *)&re); } /* draw larger separator tick to show where contig was moved from */ sprintf(cmd, "HighlightSeparator %s %d", cs->hori, orig_pos); Tcl_Eval(interp, cmd); }
/* * Complements a scaffold; both complementing each contig within it and * reversing the order of contigs in the scaffold. * * Returns 0 on success * -1 on failure */ int complement_scaffold(GapIO *io, tg_rec srec) { scaffold_t *f; int i, j, nc = ArrayMax(io->contig_order); scaffold_member_t *contigs; tg_rec *crecs; HashTable *h; reg_order ro; reg_buffer_start rs; reg_buffer_end re; if (!(f = cache_search(io, GT_Scaffold, srec))) return -1; if (!(f = cache_rw(io, f))) return -1; cache_incr(io, f); /* Complement contigs */ contigs = ArrayBase(scaffold_member_t, f->contig); for (i = 0; i < ArrayMax(f->contig); i++) { complement_contig(io, contigs[i].rec); } /* Reverse the order of the contigs in the scaffold array */ for (i = 0, j = ArrayMax(f->contig)-1; i < j; i++, j--) { scaffold_member_t cr1 = contigs[i]; contigs[i] = contigs[j]; contigs[j] = cr1; } /* * Reverse the order of contigs in the contig_order array too. * This is the part that really matters. It's also hard as the contigs * in the contig order array could be in any order and not adjacent. * For our purposes we'll just ensure the contigs in this scaffold in * the contig order array match our freshly complemented scaffold * ordering. * * We initially build a hash table of contigs in this scaffold, and * then iterate through contig_order copying out the new contigs whenever * one matches. */ h = HashTableCreate(nc, 0); for (i = 0; i < ArrayMax(f->contig); i++) { HashData hd; hd.i = 0; HashTableAdd(h, (char *)&contigs[i].rec, sizeof(tg_rec), hd, NULL); } /* Replace any contig matching the scaffold with the new order */ crecs = ArrayBase(tg_rec, io->contig_order); for (i = j = 0; i < nc; i++) { HashItem *hi; if (!(hi = HashTableSearch(h, (char *)&crecs[i], sizeof(tg_rec)))) continue; crecs[i] = contigs[j++].rec; } /* Send event messages around */ rs.job = REG_BUFFER_START; for (i = 0; i < nc; i++) { HashItem *hi; if (!(hi = HashTableSearch(h, (char *)&crecs[i], sizeof(tg_rec)))) continue; contig_notify(io, crecs[i], (reg_data *)&rs); } ro.job = REG_ORDER; for (i = 0; i < nc; i++) { HashItem *hi; if (!(hi = HashTableSearch(h, (char *)&crecs[i], sizeof(tg_rec)))) continue; ro.pos = i+1; contig_notify(io, crecs[i], (reg_data *)&ro); } /* Notify the end of our updates */ re.job = REG_BUFFER_END; for (i = 0; i < nc; i++) { HashItem *hi; if (!(hi = HashTableSearch(h, (char *)&crecs[i], sizeof(tg_rec)))) continue; contig_notify(io, crecs[i], (reg_data *)&re); } HashTableDestroy(h, 0); cache_decr(io, f); return 0; }