Exemple #1
0
/*
 * 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;
}