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); }
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); }
Color pubsItemColor(struct track *tg, void *item, struct hvGfx *hvg) /* get color from extra field */ { //pubsParseClassColors(); struct linkedFeatures *lf = item; pubsAddExtra(tg, lf); struct pubsExtra* extra = lf->extra; if (extra==NULL || (extra->color==NULL && extra->shade==-1)) return MG_BLACK; if (extra->shade != -1) return shadesOfBlue[extra->shade]; else { //printf("got item color %d", extra->color->r); return hvGfxFindRgb(hvg, extra->color); } }
struct hvGfx *oneTrackMakeTrackHvg(char *trackName, char *gifName) /* Set up a single track, load it, draw it and return the graphics object: */ { char *visStr = cloneString( cartUsualString(cart, trackName, hTrackOpenVis(trackName)) ); cartSetString(cart, trackName, visStr); struct trackDb *tdb = hTrackDbForTrack(trackName); tdbSortPrioritiesFromCart(cart, &tdb); if(tdb->subtracks) tdbSortPrioritiesFromCart(cart, &(tdb->subtracks)); struct track *tg = trackFromTrackDb(tdb); tg->visibility = hTvFromString(visStr); trackList = tg; tg->loadItems(tg); limitVisibility(tg); int height = tg->totalHeight(tg, tg->limitedVis); struct hvGfx *hvg = hvGfxOpenGif(insideWidth, height, gifName, TRUE); initColors(hvg); findTrackColors(hvg, tg); /* This is the only image we'll draw, so offset=(0,0). */ int xOff = 0, yOff = 0; MgFont *font = tl.font; hvGfxSetClip(hvg, xOff, yOff, insideWidth, tg->height); tg->drawItems(tg, winStart, winEnd, hvg, xOff, yOff, insideWidth, font, hvGfxFindRgb(hvg, &tg->color), tg->limitedVis); /* MEMORY LEAK -- Freeing items slows hgTracks down unacceptably so we * don't do it, and it has become vestigial. For example, wigFreeItems * is a no-op because the author noted that it is never invoked. */ #ifdef SLOW tg->freeItems(tg); #endif /* SLOW */ return hvg; }
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 vcfHapClusterDraw(struct track *tg, int seqStart, int seqEnd, struct hvGfx *hvg, int xOff, int yOff, int width, MgFont *font, Color color, enum trackVisibility vis) /* Split samples' chromosomes (haplotypes), cluster them by center-weighted * alpha similarity, and draw in the order determined by clustering. */ { struct vcfFile *vcff = tg->extraUiData; if (vcff->records == NULL) return; purple = hvGfxFindColorIx(hvg, 0x99, 0x00, 0xcc); undefYellow = hvGfxFindRgb(hvg, &undefinedYellowColor); enum hapColorMode colorMode = getColorMode(tg->tdb); pushWarnHandler(ignoreEm); struct vcfRecord *rec; for (rec = vcff->records; rec != NULL; rec = rec->next) vcfParseGenotypes(rec); popWarnHandler(); unsigned short gtHapCount = 0; int nRecords = slCount(vcff->records); int centerIx = getCenterVariantIx(tg, seqStart, seqEnd, vcff->records); // Limit the number of variants that we compare, to keep from timing out: // (really what we should limit is the number of distinct haplo's passed to hacTree!) // In the meantime, this should at least be a cart var... int maxVariantsPerSide = 50; int startIx = max(0, centerIx - maxVariantsPerSide); int endIx = min(nRecords, centerIx+1 + maxVariantsPerSide); struct hacTree *ht = NULL; unsigned short *gtHapOrder = clusterHaps(vcff, centerIx, startIx, endIx, >HapCount, &ht); struct vcfRecord *centerRec = NULL; int ix; // Unlike drawing order (last drawn is on top), the first mapBox gets priority, // so map center variant before drawing & mapping other variants! for (rec = vcff->records, ix=0; rec != NULL; rec = rec->next, ix++) { if (ix == centerIx) { centerRec = rec; mapBoxForCenterVariant(rec, hvg, tg, xOff, yOff, width); break; } } for (rec = vcff->records, ix=0; rec != NULL; rec = rec->next, ix++) { boolean isClustered = (ix >= startIx && ix < endIx); if (ix != centerIx) drawOneRec(rec, gtHapOrder, gtHapCount, tg, hvg, xOff, yOff, width, isClustered, FALSE, colorMode); } // Draw the center rec on top, outlined with black lines, to make sure it is very visible: drawOneRec(centerRec, gtHapOrder, gtHapCount, tg, hvg, xOff, yOff, width, TRUE, TRUE, colorMode); // Draw as much of the tree as can fit in the left label area: int extraPixel = (colorMode == altOnlyMode) ? 1 : 0; int hapHeight = tg->height- CLIP_PAD - 2*extraPixel; struct yFromNodeHelper yHelper = {0, NULL, NULL}; initYFromNodeHelper(&yHelper, yOff+extraPixel, hapHeight, gtHapCount, gtHapOrder, vcff->genotypeCount); struct titleHelper titleHelper = { NULL, 0, 0, 0, 0, NULL, NULL }; initTitleHelper(&titleHelper, tg->track, startIx, centerIx, endIx, nRecords, vcff); char *treeAngle = cartOrTdbString(cart, tg->tdb, VCF_HAP_TREEANGLE_VAR, VCF_DEFAULT_HAP_TREEANGLE); boolean drawRectangle = sameString(treeAngle, VCF_HAP_TREEANGLE_RECTANGLE); drawTreeInLabelArea(ht, hvg, yOff+extraPixel, hapHeight+CLIP_PAD, &yHelper, &titleHelper, drawRectangle); }
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); }