void hCytoBandDrawCentromere(struct hvGfx *hvg, int x, int y, int width, int height, Color bgColor, Color fgColor) /* Draw the centromere. */ { struct gfxPoly *poly; int xCen = x+width/2, yCen = y+height/2; int xEnd = x+width-1, yEnd = y+height-1; /* Draw box over centromere, may be drawn already with lettering * which we don't want. */ hvGfxBox(hvg, x, y, width, height, bgColor); char *savedHint = hvGfxGetHint(hvg,"fat"); hvGfxSetHint(hvg,"fat","on"); /* Make up triangle on left of centromere and draw. */ poly = gfxPolyNew(); gfxPolyAddPoint(poly, x, y); gfxPolyAddPoint(poly, xCen, yCen); gfxPolyAddPoint(poly, x, yEnd); hvGfxDrawPoly(hvg, poly, fgColor, TRUE); gfxPolyFree(&poly); /* Make up triangle on right of centromere and draw. */ poly = gfxPolyNew(); gfxPolyAddPoint(poly, xEnd, y); gfxPolyAddPoint(poly, xCen, yCen); gfxPolyAddPoint(poly, xEnd, yEnd); hvGfxDrawPoly(hvg, poly, fgColor, TRUE); gfxPolyFree(&poly); hvGfxSetHint(hvg,"fat",savedHint); }
void bigBedDrawDense(struct track *tg, int seqStart, int seqEnd, struct hvGfx *hvg, int xOff, int yOff, int width, MgFont *font, Color color) /* Use big-bed summary data to quickly draw bigBed. */ { struct bbiSummaryElement *summary = tg->summary; if (summary) { char *denseCoverage = trackDbSettingClosestToHome(tg->tdb, "denseCoverage"); if (denseCoverage != NULL) { double startVal = 0, endVal = atof(denseCoverage); if (endVal <= 0) { struct bbiSummaryElement sumAll = *tg->sumAll; double mean = sumAll.sumData/sumAll.validCount; double std = calcStdFromSums(sumAll.sumData, sumAll.sumSquares, sumAll.validCount); rangeFromMinMaxMeanStd(0, sumAll.maxVal, mean, std, &startVal, &endVal); } int x; for (x=0; x<width; ++x) { if (summary[x].validCount > 0) { Color color = shadesOfGray[grayInRange(summary[x].maxVal, startVal, endVal)]; hvGfxBox(hvg, x+xOff, yOff, 1, tg->heightPer, color); } } } else { int x; for (x=0; x<width; ++x) { if (summary[x].validCount > 0) { hvGfxBox(hvg, x+xOff, yOff, 1, tg->heightPer, color); } } } } freez(&tg->summary); }
void genoLayDrawSimpleChroms(struct genoLay *gl, struct hvGfx *hvg, int color) /* Draw boxes for all chromosomes in given color */ { int height = gl->chromHeight; int yOffset = gl->chromOffsetY; struct genoLayChrom *chrom; for (chrom = gl->chromList; chrom != NULL; chrom = chrom->next) hvGfxBox(hvg, chrom->x, chrom->y + yOffset, chrom->width, height, color); }
void drawUseBamWarning(struct track *tg, int seqStart, int seqEnd, struct hvGfx *hvg, int xOff, int yOff, int width, MgFont *font, Color color, enum trackVisibility vis) /* Draw a message saying that the code needs to be built with USE_BAM=1. */ { char message[512]; safef(message, sizeof(message), "Get samtools(.sourceforge.net) and recompile kent/src with USE_BAM=1"); Color yellow = hvGfxFindRgb(hvg, &undefinedYellowColor); hvGfxBox(hvg, xOff, yOff, width, tg->heightPer, yellow); hvGfxTextCentered(hvg, xOff, yOff, width, tg->heightPer, MG_BLACK, font, message); }
static void drawWiggleHorizontalLine( struct hvGfx *hvg, double where, double min0, double max0, int binCount, int y, double hFactor, int heightPer, Color lineColor ) /* Draws a blue horizontal line on a wiggle track at a specified * location based on the range and number of bins*/ { int bin; double y1; bin = -whichSampleBin( where, min0, max0, binCount); y1 = (int)((double)y+((double)bin)*hFactor+(double)heightPer); hvGfxBox(hvg, 0, y1, hvg->width, 1, lineColor); }
void bigDrawWarning(struct track *tg, int seqStart, int seqEnd, struct hvGfx *hvg, int xOff, int yOff, int width, MgFont *font, Color color, enum trackVisibility vis) /* Draw the network error message */ { char message[1024]; Color yellow = hvGfxFindRgb(hvg, &undefinedYellowColor); char *errMsg = bigWarnReformat(tg->networkErrMsg); char *nl = errMsg; int sl = strlen(errMsg); // in some cases, cannot use tg-> values, so recalc local equivalents. int heightPer = tl.fontHeight; /* Height per item line minus border. */ int lineHeight = heightPer+4; /* Height per item line including border. */ if (lineHeight > tg->height) lineHeight = tg->height; int n = bigWarnNumLines(errMsg); /* Lines of warning text */ int m = tg->height / lineHeight; /* Lines of text space available */ if (m < 1) m = 1; // make yellow background to draw user's attention to the err msg if (!sameOk(parentContainerType(tg), "multiWig")) // unless multiwig has already done it. hvGfxBox(hvg, xOff, yOff, width, tg->height, yellow); // leading blank lines if any int bl = (m-n)/2; int i; for(i=0;i<bl;++i) yOff += lineHeight; int l = 0; while (TRUE) { char *msg = nl; nl = strchr(nl,'\n'); if (nl) nl[0] = 0; if (nl || ((sl > 0) && (errMsg[sl-1]!='\n'))) { safef(message, sizeof(message), "%s", msg); hvGfxTextCentered(hvg, xOff, yOff, width, lineHeight, MG_BLACK, font, message); yOff += lineHeight; ++l; if (l > n) break; if (l > m) break; } if (!nl) break; ++nl; } freeMem(errMsg); }
void hvGfxDrawRulerBumpText(struct hvGfx *hvg, int xOff, int yOff, int height, int width, Color color, MgFont *font, int startNum, int range, int bumpX, int bumpY) /* Draw a ruler inside the indicated part of mg with numbers that start at * startNum and span range. Bump text positions slightly. */ { int tickSpan; int tickPos; double scale; int firstTick; int remainder; int end = startNum + range; int x; char tbuf[18]; int numWid; int goodNumTicks; int niceNumTicks = width/35; sprintLongWithCommas(tbuf, startNum+range); numWid = mgFontStringWidth(font, tbuf)+4+bumpX; goodNumTicks = width/numWid; if (goodNumTicks < 1) goodNumTicks = 1; if (goodNumTicks > niceNumTicks) goodNumTicks = niceNumTicks; tickSpan = figureTickSpan(range, goodNumTicks); scale = (double)width / range; firstTick = startNum + tickSpan; remainder = firstTick % tickSpan; firstTick -= remainder; for (tickPos=firstTick; tickPos<end; tickPos += tickSpan) { sprintLongWithCommas(tbuf, tickPos); numWid = mgFontStringWidth(font, tbuf)+4; x = (int)((tickPos-startNum) * scale) + xOff; hvGfxBox(hvg, x, yOff, 1, height, color); if (x - numWid >= xOff) { hvGfxTextCentered(hvg, x-numWid + bumpX, yOff + bumpY, numWid, height, color, font, tbuf); } } }
void cgLeftLabels(struct track *tg, int seqStart, int seqEnd, struct hvGfx *hvg, int xOff, int yOff, int width, int height, boolean withCenterLabels, MgFont *font, Color color, enum trackVisibility vis) /* Draw labels to the left. */ { struct chromGraphSettings *cgs = tg->customPt; if (vis == tvDense || cgs->linesAtCount == 0) { hvGfxTextRight(hvg, xOff, yOff, width - 1, height, color, font, tg->shortLabel); } else { int i; int realHeight = height; int realYoff = yOff; double minVal = cgs->minVal; double yScale; int tickSize = tl.nWidth; int numPos = tickSize * 1.25; if (withCenterLabels) { int centerLabelHeight = tl.fontHeight; realHeight -= centerLabelHeight; realYoff += centerLabelHeight; } yScale = (realHeight-1)/(cgs->maxVal - minVal); for (i=0; i<cgs->linesAtCount; ++i) { double val = cgs->linesAt[i]; int y = realHeight - 1 - (val - minVal)*yScale + realYoff; char numText[16]; hvGfxBox(hvg, xOff + width - tickSize, y, tickSize, 1, color); safef(numText, sizeof(numText), "%g", val); hvGfxTextRight(hvg, xOff, y - tl.fontHeight+2, width - numPos, tl.fontHeight, color, font, numText); } wrapTextAndCenter(hvg, xOff+1, yOff, width*5*tl.nWidth, height, font, color, tg->shortLabel); } }
void hCytoBandDrawAt(struct cytoBand *band, struct hvGfx *hvg, int x, int y, int width, int height, boolean isDmel, MgFont *font, int fontPixelHeight, Color aColor, Color bColor, Color *shades, int maxShade) /* Draw a single band in appropriate color at given position. If there's * room put in band label. */ { Color col = hCytoBandColor(band, hvg, isDmel, aColor, bColor, shades, maxShade); hvGfxBox(hvg, x, y, width, height, col); if (height >= mgFontLineHeight(font)) { char *s = abbreviatedBandName(band, font, width, isDmel); if (s != NULL) { Color textCol = hvGfxContrastingColor(hvg, col); hvGfxTextCentered(hvg, x, y, width, height, textCol, font, s); } } }
static void contigDraw(struct track *tg, int seqStart, int seqEnd, struct hvGfx *hvg, int xOff, int yOff, int width, MgFont *font, Color color, enum trackVisibility vis) /* Draw contig items. */ { struct ctgPos *ctg; int y = yOff; int heightPer = tg->heightPer; int lineHeight = tg->lineHeight; int x1,x2,w; boolean isFull = (vis == tvFull); int ix = 0; char *s; double scale = scaleForPixels(width); for (ctg = tg->items; ctg != NULL; ctg = ctg->next) { x1 = round((double)((int)ctg->chromStart-winStart)*scale) + xOff; x2 = round((double)((int)ctg->chromEnd-winStart)*scale) + xOff; /* Clip here so that text will tend to be more visible... */ if (x1 < xOff) x1 = xOff; if (x2 > xOff + width) x2 = xOff + width; w = x2-x1; if (w < 1) w = 1; hvGfxBox(hvg, x1, y, w, heightPer, color); s = abbreviateContig(ctg->contig, tl.font, w); if (s != NULL) hvGfxTextCentered(hvg, x1, y, w, heightPer, MG_WHITE, tl.font, s); if (isFull) y += lineHeight; else { mapBoxHc(hvg, ctg->chromStart, ctg->chromEnd, x1,y,w,heightPer, tg->track, tg->mapItemName(tg, ctg), tg->itemName(tg, ctg)); } ++ix; } }
void cytoBandIdeoDraw(struct track *tg, int seqStart, int seqEnd, struct hvGfx *hvg, int xOff, int yOff, int width, MgFont *font, Color color, enum trackVisibility vis) /* Draw the entire chromosome with a little red box around our current position. */ { double scale = 0; int xBorder = 4; int x1, x2; int yBorder = 0; int chromSize = hChromSize(database, chromName); struct cytoBand *cbList = NULL, *cb = NULL; scale = (double) (width - (2 * xBorder)) / chromSize; /* Subtrack 10 for the 5 pixels buffer on either side. */ tg->heightPer -= 11; tg->lineHeight -= 11; /* Time to draw the bands. */ hvGfxSetClip(hvg, xOff, yOff, width, tg->height); genericDrawItems(tg, 0, chromSize, hvg, xOff+xBorder, yOff+5, width-(2*xBorder), font, color, tvDense); x1 = round((winStart)*scale) + xOff + xBorder -1; x2 = round((winEnd)*scale) + xOff + xBorder -1; if(x1 >= x2) x2 = x1+1; yBorder = tg->heightPer + 7 + 1; /* Draw an outline around chromosome for visualization purposes. Helps to make the chromosome look better. */ hvGfxLine(hvg, xOff+xBorder, yOff+4, xOff+width-xBorder, yOff+4, MG_BLACK); hvGfxLine(hvg, xOff+xBorder, yOff+yBorder-3, xOff+width-xBorder, yOff+yBorder-3, MG_BLACK); hvGfxLine(hvg, xOff+xBorder, yOff+4, xOff+xBorder, yOff+yBorder-3, MG_BLACK); hvGfxLine(hvg, xOff+width-xBorder, yOff+4, xOff+width-xBorder, yOff+yBorder-3, MG_BLACK); /* Find and draw the centromere which is defined as the two bands with gieStain "acen" */ cbList = tg->items; for(cb = cbList; cb != NULL; cb = cb->next) { /* If centromere do some drawing. */ if(sameString(cb->gieStain, "acen")) { int cenLeft, cenRight, cenTop, cenBottom; /* Get the coordinates of the edges of the centromere. */ cenLeft = round((cb->chromStart)*scale) + xOff + xBorder; cenRight = round((cb->next->chromEnd)*scale) + xOff + xBorder; cenTop = yOff+4; cenBottom = yOff + yBorder - 3; /* Draw centromere itself. */ hCytoBandDrawCentromere(hvg, cenLeft, cenTop, cenRight - cenLeft, cenBottom-cenTop+1, MG_WHITE, hCytoBandCentromereColor(hvg)); break; } } /* Draw a red box around all positions in windows for this chromName. * Double thick so two pixels thick each. */ struct window *window; for (window=windows; window; window=window->next) { if (!sameString(chromName, window->chromName)) continue; x1 = round((window->winStart)*scale) + xOff + xBorder -1; x2 = round((window->winEnd)*scale) + xOff + xBorder -1; hvGfxBox(hvg, x1, yOff+1, x2-x1, 2, MG_RED); hvGfxBox(hvg, x1, yOff + yBorder - 1, x2-x1, 2, MG_RED); hvGfxBox(hvg, x1, yOff+1, 2, yBorder, MG_RED); hvGfxBox(hvg, x2, yOff+1, 2, yBorder, MG_RED); } hvGfxUnclip(hvg); /* Put back the lineHeight for the track now that we are done spoofing tgDrawItems(). */ tg->heightPer += 11; tg->lineHeight += 11; }
static void cgDrawEither(struct track *tg, int seqStart, int seqEnd, struct hvGfx *hvg, int xOff, int yOff, int width, MgFont *font, Color color, enum trackVisibility vis, char *binFileName) /* Draw chromosome graph - either built in or not. */ { struct chromGraphSettings *cgs = tg->customPt; int x,y,lastX=0,lastY=0, llastX = 0, llastY = 0; int height = tg->height; int maxGapToFill = cgs->maxGapToFill; int lastPos = -maxGapToFill-1; double minVal = cgs->minVal; double yScale = (height-1)/(cgs->maxVal - minVal); double xScale = scaleForPixels(width); Color myColor = cgColorLikeHgGenome(tg, hvg); /* Draw background lines in full mode. */ if (vis == tvFull && cgs->linesAtCount != 0) { int i; Color lightBlue = hvGfxFindRgb(hvg, &guidelineColor); for (i=0; i<cgs->linesAtCount; ++i) { y = height - 1 - (cgs->linesAt[i] - minVal)*yScale + yOff; hvGfxBox(hvg, xOff, y, width, 1, lightBlue); } } if (binFileName) { struct chromGraphBin *cgb = chromGraphBinOpen(binFileName); if (chromGraphBinSeekToChrom(cgb, chromName)) { int seqStartMinus = seqStart - cgs->maxGapToFill; while (chromGraphBinNextVal(cgb)) { int pos = cgb->chromStart; if (pos >= seqStartMinus) { double val = cgb->val; x = (pos - seqStart)*xScale + xOff; y = height - 1 - (val - minVal)*yScale + yOff; if (x >= xOff) { if (pos - lastPos <= maxGapToFill) { if (llastX != lastX || llastY != lastY || lastX != x || lastY != y) hvGfxLine(hvg, lastX, lastY, x, y, myColor); } else hvGfxDot(hvg, x, y, myColor); } llastX = lastX; llastY = lastY; lastX = x; lastY = y; lastPos = pos; if (pos >= seqEnd) break; } } } } else { struct sqlConnection *conn = hAllocConn(database); char query[512]; struct sqlResult *sr; char **row; /* Construct query. Set up a little more than window so that * we can draw connecting lines. */ sqlSafef(query, sizeof(query), "select chromStart,val from %s " "where chrom='%s' and chromStart>=%d and chromStart<%d", tg->table, chromName, seqStart - cgs->maxGapToFill, seqEnd + cgs->maxGapToFill); sr = sqlGetResult(conn, query); /* Loop through drawing lines from one point to another unless * the points are too far apart. */ while ((row = sqlNextRow(sr)) != NULL) { int pos = sqlUnsigned(row[0]); double val = atof(row[1]); x = (pos - seqStart)*xScale + xOff; y = height - 1 - (val - minVal)*yScale + yOff; if (x >= xOff) { if (pos - lastPos <= maxGapToFill) { if (llastX != lastX || llastY != lastY || lastX != x || lastY != y) hvGfxLine(hvg, lastX, lastY, x, y, myColor); } else hvGfxDot(hvg, x, y, myColor); } llastX = lastX; llastY = lastY; lastX = x; lastY = y; lastPos = pos; if (pos >= seqEnd) break; } sqlFreeResult(&sr); hFreeConn(&conn); } /* Do map box */ xOff = hvGfxAdjXW(hvg, xOff, width); char *encodedTrack = cgiEncode(tg->track); if (theImgBox && curImgTrack) { char link[512]; // FIXME: winStart/winEnd are not right when using a portal safef(link,sizeof(link),"%s&c=%s&o=%d&t=%d&g=%s", hgcNameAndSettings(), chromName, winStart, winEnd, encodedTrack); #ifdef IMAGEv2_SHORT_MAPITEMS if (xOff < insideX && xOff+width > insideX) warn("cgDrawEither(%s) map item spanning slices. LX:%d TY:%d RX:%d BY:%d link:[%s]", encodedTrack,xOff, yOff, xOff+width, yOff+height, link); #endif//def IMAGEv2_SHORT_MAPITEMS imgTrackAddMapItem(curImgTrack,link,NULL,xOff,yOff,xOff+width,yOff+height,tg->track); } else { hPrintf("<AREA SHAPE=RECT COORDS=\"%d,%d,%d,%d\" ", xOff, yOff, xOff+width, yOff+height); hPrintf("HREF=\"%s&o=%d&t=%d&g=%s&c=%s&l=%d&r=%d&db=%s&pix=%d\">\n", hgcNameAndSettings(), winStart, winEnd, encodedTrack, chromName, winStart, winEnd, database, tl.picWidth); } }
static void goldDrawDense(struct track *tg, int seqStart, int seqEnd, struct hvGfx *hvg, int xOff, int yOff, int width, MgFont *font, Color color, enum trackVisibility vis) /* Draw golden path items. */ { int baseWidth = seqEnd - seqStart; struct agpFrag *frag; struct agpGap *gap; int y = yOff; int heightPer = tg->heightPer; int lineHeight = tg->lineHeight; int x1,x2,w; int midLineOff = heightPer/2; boolean isFull = (vis == tvFull); Color brown = color; Color gold = tg->ixAltColor; Color pink = 0; Color pink1 = hvGfxFindColorIx(hvg, 240, 140, 140); Color pink2 = hvGfxFindColorIx(hvg, 240, 100, 100); int ix = 0; double scale = scaleForPixels(width); /* Draw gaps if any. */ if (!isFull) { int midY = y + midLineOff; for (gap = tg->customPt; gap != NULL; gap = gap->next) { if (!sameWord(gap->bridge, "no")) { drawScaledBox(hvg, gap->chromStart, gap->chromEnd, scale, xOff, midY, 1, brown); } } } for (frag = tg->items; frag != NULL; frag = frag->next) { x1 = round((double)((int)frag->chromStart-winStart)*scale) + xOff; x2 = round((double)((int)frag->chromEnd-winStart)*scale) + xOff; w = x2-x1; color = ((ix&1) ? gold : brown); pink = ((ix&1) ? pink1 : pink2); if (w < 1) w = 1; if (sameString(frag->type, "A")) color = pink; hvGfxBox(hvg, x1, y, w, heightPer, color); if (isFull) y += lineHeight; else if (baseWidth < 10000000) { char status[256]; sprintf(status, "%s:%d-%d %s %s:%d-%d", frag->frag, frag->fragStart, frag->fragEnd, frag->strand, frag->chrom, frag->chromStart, frag->chromEnd); mapBoxHc(hvg, frag->chromStart, frag->chromEnd, x1,y,w,heightPer, tg->track, frag->frag, status); } ++ix; } }
void genoLayDrawBandedChroms(struct genoLay *gl, struct hvGfx *hvg, char *db, struct sqlConnection *conn, Color *shadesOfGray, int maxShade, int defaultColor) /* Draw chromosomes with centromere and band glyphs. * Get the band data from the database. If the data isn't * there then draw simple chroms in default color instead */ { char *bandTable = "cytoBandIdeo"; int yOffset = gl->chromOffsetY; genoLayDrawSimpleChroms(gl, hvg, defaultColor); if (sqlTableExists(conn, bandTable) && !gl->allOneLine) { int centromereColor = hCytoBandCentromereColor(hvg); double pixelsPerBase = 1.0/gl->basesPerPixel; int height = gl->chromHeight; int innerHeight = gl->chromHeight-2; struct genoLayChrom *chrom; boolean isDmel = hCytoBandDbIsDmel(db); boolean bColor = hvGfxFindColorIx(hvg, 200, 150, 150); int fontPixelHeight = mgFontPixelHeight(gl->font); for (chrom = gl->chromList; chrom != NULL; chrom = chrom->next) { boolean gotAny = FALSE; struct sqlResult *sr; char **row; char query[256]; int cenX1=BIGNUM, cenX2=0; int y = chrom->y + yOffset; /* Fetch bands from database and draw them. */ safef(query, sizeof(query), "select * from %s where chrom='%s'", bandTable, chrom->fullName); sr = sqlGetResult(conn, query); while ((row = sqlNextRow(sr)) != NULL) { struct cytoBand band; int x1, x2; cytoBandStaticLoad(row, &band); x1 = pixelsPerBase*band.chromStart; x2 = pixelsPerBase*band.chromEnd; if (sameString(band.gieStain, "acen")) { /* Centromere is represented as two adjacent bands. * We'll just record the extents of it here, and draw it * in one piece later. */ if (x1 < cenX1) cenX1 = x1; if (x2 > cenX2) cenX2 = x2; } else { /* Draw band */ hCytoBandDrawAt(&band, hvg, x1+chrom->x, y+1, x2-x1, innerHeight, isDmel, gl->font, fontPixelHeight, MG_BLACK, bColor, shadesOfGray, maxShade); gotAny = TRUE; } } sqlFreeResult(&sr); /* Draw box around chromosome */ hvGfxBox(hvg, chrom->x, y, chrom->width, 1, MG_BLACK); hvGfxBox(hvg, chrom->x, y+height-1, chrom->width, 1, MG_BLACK); hvGfxBox(hvg, chrom->x, y, 1, height, MG_BLACK); hvGfxBox(hvg, chrom->x+chrom->width-1, y, 1, height, MG_BLACK); /* Draw centromere if we found one. */ if (cenX2 > cenX1) { hCytoBandDrawCentromere(hvg, cenX1+chrom->x, y, cenX2-cenX1, height, MG_WHITE, centromereColor); } } } }
static void drawOneRec(struct vcfRecord *rec, unsigned short *gtHapOrder, unsigned short gtHapCount, struct track *tg, struct hvGfx *hvg, int xOff, int yOff, int width, boolean isClustered, boolean isCenter, enum hapColorMode colorMode) /* Draw a stack of genotype bars for this record */ { unsigned int chromStartMap = vcfRecordTrimIndelLeftBase(rec); unsigned int chromEndMap = vcfRecordTrimAllelesRight(rec); const double scale = scaleForPixels(width); int x1 = round((double)(rec->chromStart-winStart)*scale) + xOff; int x2 = round((double)(rec->chromEnd-winStart)*scale) + xOff; int w = x2-x1; if (w <= 1) { x1--; w = 3; } // When coloring mode is altOnly, we draw one extra pixel row at the top & one at bottom // to show the locations of variants, since the reference alleles are invisible: int extraPixel = 0; int hapHeight = tg->height - CLIP_PAD; if (colorMode == altOnlyMode) { hvGfxLine(hvg, x1, yOff, x2, yOff, (isClustered ? purple : shadesOfGray[5])); extraPixel = 1; hapHeight -= extraPixel*2; } double hapsPerPix = (double)gtHapCount / hapHeight; int pixIx; for (pixIx = 0; pixIx < hapHeight; pixIx++) { int gtHapOrderIxStart = (int)(hapsPerPix * pixIx); int gtHapOrderIxEnd = round(hapsPerPix * (pixIx + 1)); if (gtHapOrderIxEnd == gtHapOrderIxStart) gtHapOrderIxEnd++; int unks = 0, refs = 0, alts = 0; int gtHapOrderIx; for (gtHapOrderIx = gtHapOrderIxStart; gtHapOrderIx < gtHapOrderIxEnd; gtHapOrderIx++) { int gtHapIx = gtHapOrder[gtHapOrderIx]; int hapIx = gtHapIx & 1; int gtIx = gtHapIx >>1; struct vcfGenotype *gt = &(rec->genotypes[gtIx]); if (gt->isPhased || gt->isHaploid || (gt->hapIxA == gt->hapIxB)) { int alIx = hapIx ? gt->hapIxB : gt->hapIxA; if (alIx < 0) unks++; else if (alIx > 0) alts++; else refs++; } else unks++; } int y = yOff + extraPixel + pixIx; Color col; if (colorMode == baseMode) col = colorByBase(refs, alts, unks, rec->alleles[0], rec->alleles[1]); else if (colorMode == refAltMode) col = colorByRefAlt(refs, alts, unks); else col = colorByAltOnly(refs, alts, unks); if (col != MG_WHITE) hvGfxLine(hvg, x1, y, x2, y, col); } int yBot = yOff + tg->height - CLIP_PAD - 1; if (isCenter) { if (colorMode == altOnlyMode) { // Colorful outline to distinguish this variant: hvGfxLine(hvg, x1-1, yOff, x1-1, yBot, purple); hvGfxLine(hvg, x2+1, yOff, x2+1, yBot, purple); hvGfxLine(hvg, x1-1, yOff, x2+1, yOff, purple); hvGfxLine(hvg, x1-1, yBot, x2+1, yBot, purple); } else { // Thick black lines to distinguish this variant: hvGfxBox(hvg, x1-3, yOff, 3, tg->height, MG_BLACK); hvGfxBox(hvg, x2, yOff, 3, tg->height, MG_BLACK); hvGfxLine(hvg, x1-2, yOff, x2+2, yOff, MG_BLACK); hvGfxLine(hvg, x1-2, yBot, x2+2, yBot, MG_BLACK); } // Mouseover was handled already by mapBoxForCenterVariant } else { struct dyString *dy = dyStringNew(0); gtSummaryString(rec, dy); mapBoxHgcOrHgGene(hvg, chromStartMap, chromEndMap, x1, yOff, w, tg->height, tg->track, rec->name, dy->string, NULL, TRUE, NULL); } if (colorMode == altOnlyMode) hvGfxLine(hvg, x1, yBot, x2, yBot, (isClustered ? purple : shadesOfGray[5])); }
static void multiWigDraw(struct track *tg, int seqStart, int seqEnd, struct hvGfx *hvg, int xOff, int yOff, int width, MgFont *font, Color color, enum trackVisibility vis) /* Draw items in multiWig container. */ { struct track *subtrack; boolean errMsgShown = FALSE; int y = yOff; boolean errMsgFound = FALSE; int numTracks = 0; // determine if any subtracks had errors and count them up for (subtrack = tg->subtracks; subtrack != NULL; subtrack = subtrack->next) { if (isSubtrackVisible(subtrack) ) { numTracks++; if (subtrack->networkErrMsg) errMsgFound = TRUE; } } if (errMsgFound) { Color yellow = hvGfxFindRgb(hvg, &undefinedYellowColor); hvGfxBox(hvg, xOff, yOff, width, tg->height, yellow); } struct wigCartOptions *wigCart = tg->wigCartData; struct wigGraphOutput *wgo = setUpWgo(xOff, yOff, width, tg->height, numTracks, wigCart, hvg); // we want to the order to be the same in all the modes if (wigCart->aggregateFunction == wiggleAggregateStacked) slReverse(&tg->subtracks); /* Cope with autoScale and stacked bars - we do it here rather than in the child tracks, so that * all children can be on same scale. */ double minVal, maxVal; /* Force load of all predraw arrays so can do calcs. Build up list, and then * figure out max/min. No worries about multiple loading, the loaders protect * themselves. */ struct slRef *refList = NULL; for (subtrack = tg->subtracks; subtrack != NULL; subtrack = subtrack->next) { if (isSubtrackVisible(subtrack)) { struct preDrawContainer *pre = subtrack->loadPreDraw(subtrack, seqStart, seqEnd, width); if (pre != NULL) // pre maybe null if the load fails { preDrawWindowFunction(pre->preDraw, pre->preDrawSize, wigCart->windowingFunction, wigCart->transformFunc, wigCart->doNegative); preDrawSmoothing(pre->preDraw, pre->preDrawSize, wigCart->smoothingWindow); pre->smoothingDone = TRUE; refAdd(&refList, pre); } } } slReverse(&refList); minMaxVals(refList, &minVal, &maxVal, wigCart->windowingFunction, wigCart->alwaysZero, wgo->yOffsets); slFreeList(&refList); if (!wigCart->autoScale) { minVal = wigCart->minY; maxVal = wigCart->maxY; } /* Loop through again setting up the wigCarts of the children to have minY/maxY for * our limits and autoScale off. */ for (subtrack = tg->subtracks; subtrack != NULL; subtrack = subtrack->next) { if (!isSubtrackVisible(subtrack)) continue; struct wigCartOptions *wigCart = subtrack->wigCartData; wigCart->minY = minVal; wigCart->maxY = maxVal; wigCart->autoScale = wiggleScaleManual; struct preDrawContainer *pre = subtrack->preDrawContainer; if (pre != NULL) // pre maybe null if the load fails { pre->graphUpperLimit = maxVal; pre->graphLowerLimit = minVal; } } int numTrack = 0; for (subtrack = tg->subtracks; subtrack != NULL; subtrack = subtrack->next) { if (isSubtrackVisible(subtrack)) { if (!subtrack->networkErrMsg || !errMsgShown) { if (subtrack->networkErrMsg) errMsgShown = TRUE; wgo->numTrack = numTrack++; subtrack->wigGraphOutput = wgo; int height = subtrack->totalHeight(subtrack, vis); hvGfxSetClip(hvg, xOff, y, width, height); if (wigCart->aggregateFunction != wiggleAggregateNone) subtrack->lineHeight = tg->lineHeight; subtrack->drawItems(subtrack, seqStart, seqEnd, hvg, xOff, y, width, font, color, vis); if (wigCart->aggregateFunction == wiggleAggregateNone) { y += height + 1; wgo->yOff = y; } hvGfxUnclip(hvg); } } } if (wigCart->aggregateFunction == wiggleAggregateTransparent) { floatPicIntoHvg(wgo->image, xOff, yOff, hvg); floatPicFree((struct floatPic **)&wgo->image); } char *url = trackUrl(tg->track, chromName); mapBoxHgcOrHgGene(hvg, seqStart, seqEnd, xOff, yOff, width, tg->height, tg->track, tg->track, NULL, url, TRUE, NULL); }