int basePositionToXAxis( int base, int seqStart, int seqEnd, int width, int xOff ) { double scale = scaleForPixels(width); double x1 = round((double)((int)base-seqStart)*scale) + xOff; return(x1); }
void mapBoxForCenterVariant(struct vcfRecord *rec, struct hvGfx *hvg, struct track *tg, int xOff, int yOff, int width) /* Special mouseover for center variant */ { struct dyString *dy = dyStringNew(0); unsigned int chromStartMap = vcfRecordTrimIndelLeftBase(rec); unsigned int chromEndMap = vcfRecordTrimAllelesRight(rec); gtSummaryString(rec, dy); dyStringAppend(dy, " Haplotypes sorted on "); char *centerChrom = cartOptionalStringClosestToHome(cart, tg->tdb, FALSE, "centerVariantChrom"); if (centerChrom == NULL || !sameString(chromName, centerChrom)) dyStringAppend(dy, "middle variant by default. "); else dyStringAppend(dy, "this variant. "); dyStringAppend(dy, "To anchor sorting to a different variant, click on that variant and " "then click on the 'Use this variant' button below the variant name."); 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; } mapBoxHgcOrHgGene(hvg, chromStartMap, chromEndMap, x1, yOff, w, tg->height, tg->track, rec->name, dy->string, NULL, TRUE, NULL); }
static void altGraphXDrawPackTrack(struct track *tg, int seqStart, int seqEnd, struct hvGfx *hvg, int xOff, int yOff, int width, MgFont *font, Color color, enum trackVisibility vis) /* Draws the blocks for an alt-spliced gene and the connections */ { int heightPer = tg->heightPer; int lineHeight = tg->lineHeight; double scale = scaleForPixels(width); if(vis == tvFull) { hvGfxSetClip(hvg, insideX, yOff, insideWidth, tg->height); altGraphXDrawPack(tg->items, tg->ss, hvg, xOff, yOff, width, heightPer, lineHeight, winStart, winEnd, scale, font, color, shadesOfGray, tg->track, altGraphXMap); hvGfxUnclip(hvg); } }
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; } }
struct preDrawContainer *bedGraphLoadPreDraw(struct track *tg, int seqStart, int seqEnd, int width) /* Do bits that load the predraw buffer tg->preDrawContainer. */ { /* Just need to do this once... */ if (tg->preDrawContainer) return tg->preDrawContainer; struct bedGraphItem *wi; double pixelsPerBase = scaleForPixels(width); double basesPerPixel = 1.0; int i; /* an integer loop counter */ if (pixelsPerBase > 0.0) basesPerPixel = 1.0 / pixelsPerBase; /* Allocate predraw and save it and related info in the track. */ struct preDrawContainer *pre = tg->preDrawContainer = initPreDrawContainer(width); struct preDrawElement *preDraw = pre->preDraw; /* to accumulate everything in prep for draw */ int preDrawZero = pre->preDrawZero; /* location in preDraw where screen starts */ int preDrawSize = pre->preDrawSize; /* size of preDraw array */ /* walk through all the data fill in the preDraw array */ for (wi = tg->items; wi != NULL; wi = wi->next) { double dataValue = wi->dataValue; /* the data value to graph */ /* Ready to draw, what do we know: * the feature being processed: * chrom coords: [wi->start : wi->end) * its data value: dataValue = wi->dataValue * * The drawing window, in pixels: * xOff = left margin, yOff = top margin, h = height of drawing window * drawing window in chrom coords: seqStart, seqEnd * 'basesPerPixel' is known, 'pixelsPerBase' is known */ /* let's check end point screen coordinates. If they are * the same, then this entire data block lands on one pixel, * It is OK if these end up + or -, we do want to * keep track of pixels before and after the screen for * later smoothing operations */ int x1 = (wi->start - seqStart) * pixelsPerBase; int x2 = (wi->end - seqStart) * pixelsPerBase; if (x2 > x1) { for (i = x1; i <= x2; ++i) { int xCoord = preDrawZero + i; if ((xCoord >= 0) && (xCoord < preDrawSize)) { ++preDraw[xCoord].count; if (dataValue > preDraw[xCoord].max) preDraw[xCoord].max = dataValue; if (dataValue < preDraw[xCoord].min) preDraw[xCoord].min = dataValue; preDraw[xCoord].sumData += dataValue; preDraw[xCoord].sumSquares += dataValue * dataValue; } } } else { /* only one pixel for this block of data */ int xCoord = preDrawZero + x1; /* if the point falls within our array, record it. * the (wi->validCount > 0) is a safety check. It * should always be true unless the data was * prepared incorrectly. */ if ((xCoord >= 0) && (xCoord < preDrawSize)) { ++preDraw[xCoord].count; if (dataValue > preDraw[xCoord].max) preDraw[xCoord].max = dataValue; if (dataValue < preDraw[xCoord].min) preDraw[xCoord].min = dataValue; preDraw[xCoord].sumData += dataValue; preDraw[xCoord].sumSquares += dataValue * dataValue; } } } /* for (wi = tg->items; wi != NULL; wi = wi->next) */ return pre; }
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 wiggleLinkedFeaturesDraw(struct track *tg, int seqStart, int seqEnd, struct hvGfx *hvg, int xOff, int yOff, int width, MgFont *font, Color color, enum trackVisibility vis) /* Currently this routine is adapted from Terry's * linkedFeatureSeriesDraw() routine. * It is called for 'sample' tracks as specified in the trackDb.ra. * and it looks at the cart to decide whether to interpolate, fill blocks, * and use anti-aliasing.*/ { int i; struct linkedFeatures *lf; struct simpleFeature *sf; int y = yOff; int heightPer = tg->heightPer; int lineHeight = tg->lineHeight; int x1,x2; boolean isFull = (vis == tvFull); Color bColor = tg->ixAltColor; double scale = scaleForPixels(width); int prevX = -1; int gapPrevX = -1; double prevY = -1; double y1 = -1, y2; int ybase; int sampleX, sampleY; /* A sample in sample coordinates. * Sample X coordinate is chromosome coordinate. * Sample Y coordinate is usually 0-1000 */ int binCount = 1.0/tg->scaleRange; /* Maximum sample Y coordinate. */ int bin; /* Sample Y coordinates are first converted to * bin coordinates, and then to pixels. I'm not * totally sure why. */ int currentX, currentXEnd, currentWidth; int leftSide, rightSide; int noZoom = 1; enum wiggleOptEnum wiggleType; char *interpolate = NULL; char *aa = NULL; boolean antiAlias = FALSE; int fill; int lineGapSize; double min0, max0; char o1[128]; /* Option 1 - linear interp */ char o2[128]; /* Option 2 - anti alias */ char o3[128]; /* Option 3 - fill */ char o4[128]; /* Option 4 - minimum vertical range cutoff of plot */ char o5[128]; /* Option 5 - maximum vertical range cutoff of plot */ char o6[128]; /* Option 6 - max gap where interpolation is still done */ char cartStr[64]; char *fillStr; double hFactor; double minRange, maxRange; double minRangeCutoff, maxRangeCutoff; Color gridColor = hvGfxFindRgb(hvg, &guidelineColor); /* for horizontal lines*/ lf=tg->items; if(lf==NULL) return; //take care of cart options safef( o1, 128,"%s.linear.interp", tg->track); safef( o2, 128, "%s.anti.alias", tg->track); safef( o3, 128,"%s.fill", tg->track); safef( o4, 128,"%s.min.cutoff", tg->track); safef( o5, 128,"%s.max.cutoff", tg->track); safef( o6, 128,"%s.interp.gap", tg->track); interpolate = cartUsualString(cart, o1, "Linear Interpolation"); wiggleType = wiggleStringToEnum(interpolate); aa = cartUsualString(cart, o2, "on"); antiAlias = sameString(aa, "on"); //don't fill gcPercent track by default (but fill others) if(sameString( tg->table, "pGC") && sameString(database,"zooHuman3")) { fillStr = cartUsualString(cart, o3, "0"); } else { fillStr = cartUsualString(cart, o3, "1"); } fill = atoi(fillStr); cartSetString(cart, o3, fillStr ); //the 0.1 is so the label doesn't get truncated with integer valued user input min //display range. minRangeCutoff = max( atof(cartUsualString(cart,o4,"0.0"))-0.1, tg->minRange ); maxRangeCutoff = min( atof(cartUsualString(cart,o5,"1000.0"))+0.1, tg->maxRange); lineGapSize = atoi(cartUsualString(cart, o6, "200")); //update cart settings to reflect truncated range cutoff values cartSetString( cart, "win", "F" ); safef( cartStr, 64, "%g", minRangeCutoff ); cartSetString( cart, o4, cartStr ); safef( cartStr, 64, "%g", maxRangeCutoff ); cartSetString( cart, o5, cartStr ); heightPer = tg->heightPer+1; hFactor = (double)heightPer*tg->scaleRange; //errAbort( "min=%g, max=%g\n", minRangeCutoff, maxRangeCutoff ); if( sameString( tg->table, "zoo" ) || sameString( tg->table, "zooNew" ) ) binCount = binCount - 100; //save some space at top, between each zoo species minRange = whichSampleBin( minRangeCutoff, tg->minRange, tg->maxRange, binCount ); maxRange = whichSampleBin( maxRangeCutoff, tg->minRange, tg->maxRange, binCount ); //errAbort( "(%g,%g) cutoff=(%g,%g)\n", tg->minRange, tg->maxRange, minRangeCutoff, maxRangeCutoff ); if( sameString( tg->table, "zoo" ) || sameString( tg->table, "zooNew" ) ) { /*Always interpolate zoo track (since gaps are explicitly defined*/ lineGapSize = -1; } else if( tg->minRange == 0 && tg->maxRange == 8 ) //range for all L-score tracks { if( isFull ) { min0 = whichSampleNum( minRange, tg->minRange, tg->maxRange, binCount ); max0 = whichSampleNum( maxRange, tg->minRange, tg->maxRange, binCount ); for( i=1; i<=6; i++ ) drawWiggleHorizontalLine(hvg, (double)i, min0, max0, binCount, y, hFactor, heightPer, gridColor ); } } for(lf = tg->items; lf != NULL; lf = lf->next) { gapPrevX = -1; prevX = -1; ybase = (int)((double)y+hFactor+(double)heightPer); for (sf = lf->components; sf != NULL; sf = sf->next) { sampleX = sf->start; sampleY = sf->end - sampleX; // Stange encoding but so it is. // It is to deal with the fact that // for a BED: sf->end = sf->start + length // but in our case length = height (or y-value) // so to recover height we take // height = sf->end - sf->start. // Otherwise another sf variable would // be needed. /*mapping or sequencing gap*/ if (sampleY == 0) { bin = -whichSampleBin( (int)((maxRange - minRange)/5.0+minRange), minRange, maxRange, binCount ); y1 = (int)((double)y+((double)bin)* hFactor+(double)heightPer); if( gapPrevX >= 0 ) drawScaledBox(hvg, sampleX, gapPrevX, scale, xOff, (int)y1, (int)(.10*heightPer), shadesOfGray[2]); gapPrevX = sampleX; prevX = -1; /*connect next point with gray bar too*/ continue; } if (sampleY > maxRange) sampleY = maxRange; if (sampleY < minRange) sampleY = minRange; bin = -whichSampleBin( sampleY, minRange, maxRange, binCount ); x1 = round((double)(sampleX-winStart)*scale) + xOff; y1 = (int)((double)y+((double)bin)* hFactor+(double)heightPer); if (prevX > 0) { y2 = prevY; x2 = round((double)(prevX-winStart)*scale) + xOff; if( wiggleType == wiggleLinearInterpolation ) /*connect samples*/ { if( lineGapSize < 0 || prevX - sampleX <= lineGapSize ) /*don't interpolate over large gaps*/ { if (fill) hvGfxFillUnder(hvg, x1,y1, x2,y2, ybase, bColor); else hvGfxLine(hvg, x1,y1, x2,y2, color); } } } //if( x1 < 0 || x1 > tl.picWidth ) //printf("x1 = %d, sampleX=%d, winStart = %d\n<br>", x1, sampleX, winStart ); if( x1 >= 0 && x1 <= tl.picWidth ) { /* Draw the points themselves*/ drawScaledBox(hvg, sampleX, sampleX+1, scale, xOff, (int)y1-1, 3, color); if( fill ) drawScaledBox(hvg, sampleX, sampleX+1, scale, xOff, (int)y1+2, ybase-y1-2, bColor); } prevX = gapPrevX = sampleX; prevY = y1; } leftSide = max( tg->itemStart(tg,lf), winStart ); rightSide = min( tg->itemEnd(tg,lf), winEnd ); currentX = round((double)((int)leftSide-winStart)*scale) + xOff; currentXEnd = round((double)((int)rightSide-winStart)*scale) + xOff; currentWidth = currentXEnd - currentX; if( noZoom && isFull ) { fprintf(stderr, "mapBoxHc(id: %s;) in wiggleLinkedFeatures\n", tg->track); mapBoxHc(hvg, lf->start, lf->end, currentX ,y, currentWidth, heightPer, tg->track, tg->mapItemName(tg, lf), tg->itemName(tg, lf)); if( lf->next != NULL ) y += sampleUpdateY( lf->name, lf->next->name, lineHeight ); else y += lineHeight; } } }
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; } }
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])); }