/* Last edited: Feb 6 11:04 2004 (rnc) */ /* file: zmapbccol.c * Author: Simon Kelley (srk@sanger.ac.uk) * Copyright (c) Sanger Institute, 2003 *------------------------------------------------------------------- * Zmap is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * or see the on-line version at http://www.gnu.org/copyleft/gpl.txt *------------------------------------------------------------------- * This file is part of the ZMap genome database package * and was written by * Rob Clack (Sanger Institute, UK) rnc@sanger.ac.uk, * Ed Griffiths (Sanger Institute, UK) edgrif@sanger.ac.uk and * Simon Kelley (Sanger Institute, UK) srk@sanger.ac.uk */ /* Generic box drawing column code */ /* This code was written on the day the US and UK started the Second Oil War. I think the module name "nbc" is somehow appropriate - srk */ #include #include #include #include typedef enum { DEFAULT=0, WIDTH, OFFSET, HIST } BoxColModeType; typedef struct { MethodOverlapModeType overlap_mode ; /* See wh/method.h */ /* following not under user control */ float offset ; BOOL isDown ; BoxColModeType mode ; float fmax ; BUMP bump ; Associator cluster ; /* only non-zero if METHOD_CLUSTER */ int clusterCount ; int width; float histBase; } nbcPrivate; static void nbcFinalise(void *arg) { nbcPrivate *priv = (nbcPrivate *)arg; if (priv->bump) bumpDestroy(priv->bump); } void nbcInit(ZMapWindow *window, ZMapColumn *col) { srMeth *meth = srMethodFromID(window->root->zMapRegion, col->meth); nbcPrivate *bc = handleAlloc(nbcFinalise, window->root->look->handle, sizeof(nbcPrivate)); col->private = bc; if (meth->flags & METHOD_SCORE) { bc->mode = WIDTH; if (meth->flags & METHOD_SCORE_BY_OFFSET && !col->isFrame) bc->mode = OFFSET ; else if (meth->flags & METHOD_SCORE_BY_HIST) bc->mode = HIST ; /* checks to prevent arithmetic crash */ if (bc->mode == OFFSET) { if (!meth->minScore) meth->minScore = 1 ; } else { if (meth->maxScore == meth->minScore) meth->maxScore = meth->minScore + 1 ; } } else /* none of the SCORE_BY_xxx flags set */ bc->mode = DEFAULT ; if (meth->width) { if (bc->mode == WIDTH && meth->flags & METHOD_SCORE_BY_OFFSET && meth->width > 2) bc->width = 2 ; else bc->width = meth->width ; } else /* the method doesn't set the width */ { if (bc->mode == OFFSET) bc->width = 7 ; else bc->width = 2 ; } if (bc->mode == HIST) { /* normalise the BoxCol's histBase */ if (meth->minScore == meth->maxScore) bc->histBase = meth->minScore ; else bc->histBase = (meth->histBase - meth->minScore) / (meth->maxScore - meth->minScore) ; if (bc->histBase < 0) bc->histBase = 0 ; if (bc->histBase > 1) bc->histBase = 1 ; bc->fmax = (bc->width * bc->histBase) + 0.2 ; } else bc->fmax = 0 ; } static void nbcCalcBox (srMeth *methp, nbcPrivate *bc, float *x1p, float *x2p, float *y1p, float *y2p, float score) { int xoff ; float x1, x2, y1, y2; float left, dx; float numerator, denominator ; double logdeux = log((double)2.0) ; numerator = score - methp->minScore ; denominator = methp->maxScore - methp->minScore ; left = *x1p; y1 = *y1p; y2 = *y2p; switch (bc->mode) { case OFFSET: if (denominator == 0) /* catch div by zero */ { if (numerator < 0) dx = 0.8 ; else if (numerator > 0) dx = 3 ; } else { dx = 1 + (((float)numerator)/ ((float)(denominator))) ; } if (dx < .8) dx = .8 ; if (dx > 3) dx = 3 ; /* allow some leeway & catch dx == 0 */ dx = bc->width * log((double)dx)/logdeux ; x1 = left + dx ; x2 = left + dx + .9 ; if (bc->fmax < dx + 1.5) bc->fmax = dx + 1.5 ; break ; case HIST: if (denominator == 0) /* catch div by zero */ { if (numerator < 0) dx = 0 ; else if (numerator > 1) dx = 1 ; } else { dx = numerator / denominator ; if (dx < 0) dx = 0 ; if (dx > 1) dx = 1 ; } x1 = left + (bc->width * bc->histBase) ; x2 = left + (bc->width * dx) ; if (bc->fmax < bc->width*dx) bc->fmax = bc->width*dx ; break ; case WIDTH: if (denominator == 0) /* catch div by zero */ { if (numerator < 0) dx = 0.25 ; else if (numerator > 0) dx = 1 ; } else { dx = 0.25 + ((0.75 * numerator) / denominator) ; } if (dx < 0.25) dx = 0.25 ; if (dx > 1) dx = 1 ; /* !WARNING! fall-through */ case DEFAULT: if (bc->mode == DEFAULT) dx = 0.75 ; xoff = 1 ; if (bc->bump) bumpItem (bc->bump, 2, (y2-y1), &xoff, &y1) ; #if 0 else if (bc->cluster) /* one subcolumn per key */ { void *v ; if (assFind (bc->cluster, assVoid(seg->parent), &v)) xoff = assInt(v) ; else { xoff = ++bc->clusterCount ; assInsert (bc->cluster, assVoid(seg->parent), assVoid(xoff)) ; } } #endif x1 = left + (0.5 * bc->width * (xoff - dx)) ; x2 = left + (0.5 * bc->width * (xoff + dx)) ; if (bc->fmax < 0.5*bc->width*(xoff+1)) bc->fmax = 0.5*bc->width*(xoff+1) ; break ; default: messcrash("Unknown bc->mode in fMapShowHomol(): %d", bc->mode) ; } *x1p = x1; *x2p = x2; *y1p = y1; *y2p = y2; } /* nbcDrawBox */ struct geneSelectData{ SEG *seg; BOOL isIntron; int exonNumber; }; void zMapGeneDraw(ZMapWindow *window, ZMapColumn *col, float *offset, int frame) { ZMapRegion *zMapRegion = window->root->zMapRegion; srMeth *meth = srMethodFromID(zMapRegion, col->meth); int i, j; int box; nbcPrivate *bc = (nbcPrivate *)col->private; float maxwidth = *offset; if (meth && (meth->flags & METHOD_BUMPABLE)) bc->bump = bumpCreate(30, 0); else bc->bump = NULL; for (i=0; i < arrayMax(zMapRegion->segs); i++) { SEG *seg = arrp(zMapRegion->segs, i, SEG); if (seg->method == col->meth && seg->type == col->type && zmIsOnScreen(window, seg->x1, seg->x2)) { Array exons = seg->u.transcript.exons; float e1, e2, y, x; int xoff = 1; struct geneSelectData *sd; if (bc->bump) bumpItem(bc->bump, 1, seg->x2 - seg->x1, &xoff, &y); x = *offset + xoff; if (x > maxwidth) maxwidth = x; /* NB the code below draws all the introns before drawing any of the exons. This is deliberate as otherwise the background on the adjoining intron obscures a little bit of the next exon. */ for(j = 1; j window, array(exons, j-1, srExon).x2); e2 = zmScreenCoord(col->window, array(exons, j, srExon).x1); middle = 0.5 * (e1 + e2); box = graphBoxStart(); sd = (struct geneSelectData *) halloc(sizeof(struct geneSelectData), window->drawHandle); sd->exonNumber = j; sd->isIntron = TRUE; sd->seg = seg; zmRegBox(window, box, col, sd); graphLine(x+0.5, e1, x+0.9, middle); graphLine(x+0.9, middle, x+0.5, e2); graphBoxEnd(); graphBoxDraw(box, meth->colour, -1) ; } for (j = 0; j window, array(exons, j, srExon).x1); e2 = zmScreenCoord(col->window, array(exons, j, srExon).x2); sd = (struct geneSelectData *) halloc(sizeof(struct geneSelectData), window->drawHandle); box = graphBoxStart(); sd->exonNumber = j; sd->isIntron = FALSE; sd->seg = seg; e2 = zmScreenCoord(col->window, array(exons, j, srExon).x2); zmRegBox(window, box, col, sd); graphRectangle(x, e1, x+1, e2); graphBoxEnd(); graphBoxDraw(box, meth->colour, -1) ; } } } if (bc->bump) bumpDestroy (bc->bump); *offset = maxwidth + 2.0 ; } void geneSelect(ZMapWindow *window, ZMapColumn *col, void *arg, int box, double x, double y, BOOL isSelect) { struct geneSelectData *sd = (struct geneSelectData *)arg; SEG *seg = sd->seg; Array exons = seg->u.transcript.exons; Coord x1, x2; char *string; srMeth *meth = srMethodFromID(window->root->zMapRegion, col->meth); int colour = WHITE; if (isSelect) { colour = LIGHTRED; if (sd->isIntron) { x1 = arr(exons, sd->exonNumber-1, srExon).x2 + 1 ; x2 = arr(exons, sd->exonNumber, srExon).x1 - 1 ; } else { x1 = arr(exons, sd->exonNumber, srExon).x1; x2 = arr(exons, sd->exonNumber, srExon).x2; } string = g_strdup_printf("%s [%f] %d %d", seg->id, seg->score, zmVisibleCoord(window->root, x1), zmVisibleCoord(window->root, x2)); gtk_entry_set_text(GTK_ENTRY(window->root->look->infoSpace), string); g_free(string); } graphBoxDraw(box, meth->colour, colour); } void zMapFeatureColumn(ZMapWindow *window, ZMapColumn *col, float *offset, int frame) { ZMapRegion *zMapRegion = window->root->zMapRegion; srMeth *meth = srMethodFromID(zMapRegion, col->meth); int i; nbcPrivate *bc = (nbcPrivate *)col->private; float maxwidth = *offset; if (meth->flags & METHOD_BUMPABLE) bc->bump = bumpCreate(30, 0); else bc->bump = NULL; for (i=0; i < arrayMax(zMapRegion->segs); i++) { SEG *seg = arrp(zMapRegion->segs, i, SEG); if (seg->method == col->meth && seg->type == col->type && zmIsOnScreen(window, seg->x1, seg->x2)) { int box = graphBoxStart(); float y1, y2, x1, x2; y1 = zmScreenCoord(col->window, seg->x1); y2 = zmScreenCoord(col->window, seg->x2+1) ; x1 = *offset; nbcCalcBox(meth, bc, &x1, &x2, &y1, &y2, seg->score); graphRectangle(x1, y1, x2, y2); graphBoxEnd(); graphBoxDraw (box, BLACK, meth->colour) ; zmRegBox(window, box, col, seg); if (x2 > maxwidth) maxwidth = x2; } } if (bc->bump) bumpDestroy (bc->bump); *offset = maxwidth + 0.5 ; } void nbcSelect(ZMapWindow *window, ZMapColumn *col, void *arg, int box, double x, double y, BOOL isSelect) { SEG *seg = (SEG *)arg; char *string = g_strdup_printf("%s [%f] %d %d", seg->id, seg->score, zmVisibleCoord(window->root, seg->x1), zmVisibleCoord(window->root, seg->x2)); gtk_entry_set_text(GTK_ENTRY(window->root->look->infoSpace), string); g_free(string); } /************************ end of file **********************************/