60c2f9b22552a66b86e65a922da72a6b18fa5d10 angie Mon May 23 15:56:43 2011 -0700 Feature #3711 (VCF haplotype clustering): David's suggestion:add mouseover text for the variant used as the center. diff --git src/hg/hgTracks/vcfTrack.c src/hg/hgTracks/vcfTrack.c index 420ade8..cf61389 100644 --- src/hg/hgTracks/vcfTrack.c +++ src/hg/hgTracks/vcfTrack.c @@ -360,32 +360,41 @@ if (revCmplDisp) { reverseComplement(rec->ref, strlen(rec->ref)); for (i=0; i < altCount; i++) reverseComplement(altAlleles[i], strlen(altAlleles[i])); } dyStringPrintf(dy, "%s/%s:%d %s/%s:%d %s/%s:%d", rec->ref, rec->ref, gtRefRefCount, rec->ref, altAlleles[0], gtRefAltCount, altAlleles[0], altAlleles[0], gtAltAltCount); if (gtOtherCount > 0) dyStringPrintf(dy, " other:%d", gtOtherCount); return dy->string; } +static char *centerPosCartVarName(struct trackDb *tdb) +// Return track.centerVariantPos setting (may be NULL) +{ +static char cartVar[512]; +safef(cartVar, sizeof(cartVar), "%s.centerVariantPos", tdb->track); +return cartVar; +} + static void drawOneRec(struct vcfRecord *rec, unsigned short *gtHapOrder, int gtHapEnd, - struct track *tg, struct hvGfx *hvg, int xOff, int yOff, int width) + struct track *tg, struct hvGfx *hvg, int xOff, int yOff, int width, + boolean isCenter) /* Draw a stack of genotype bars for this record */ { static struct dyString *tmp = NULL; if (tmp == NULL) tmp = dyStringNew(0); char *altAlleles[256]; int altCount; const int lineHeight = tg->lineHeight; const int itemHeight = tg->heightPer; 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) { @@ -394,43 +403,65 @@ } int y = yOff; dyStringClear(tmp); dyStringAppend(tmp, rec->alt); altCount = chopCommas(tmp->string, altAlleles); int gtHapOrderIx; for (gtHapOrderIx = 0; gtHapOrderIx < gtHapEnd; gtHapOrderIx++) { int gtHapIx = gtHapOrder[gtHapOrderIx]; int hapIx = gtHapIx & 1; int gtIx = gtHapIx >>1; struct vcfGenotype *gt = &(rec->genotypes[gtIx]); y = drawOneHap(gt, hapIx, rec->ref, altAlleles, altCount, hvg, x1, y, w, itemHeight, lineHeight); } +char *mouseoverText = gtSummaryString(rec, altAlleles, altCount); +if (isCenter) + { + // Thick black lines to distinguish this variant: + int yBot = yOff + tg->height - 2; + hvGfxBox(hvg, x1-3, yOff, 3, tg->height, MG_BLACK); + hvGfxBox(hvg, x2+1, 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); + // Special mouseover instructions: + static struct dyString *dy = NULL; + if (dy == NULL) + dy = dyStringNew(0); + dyStringPrintf(dy, "%s Haplotypes sorted on ", mouseoverText); + char *cartVar = centerPosCartVarName(tg->tdb); + char *centerPos = cartOptionalString(cart, cartVar); + if (centerPos == NULL) + 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 link below the variant name."); + mouseoverText = dy->string; + } mapBoxHgcOrHgGene(hvg, rec->chromStart, rec->chromEnd, x1, yOff, w, tg->height, tg->track, - rec->name, gtSummaryString(rec, altAlleles, altCount), - NULL, TRUE, NULL); + rec->name, mouseoverText, NULL, TRUE, NULL); } static int getCenterVariantIx(struct track *tg, int seqStart, int seqEnd, struct vcfRecord *records) // If the user hasn't specified a local variant/position to use as center, // just use the median variant in window. { int defaultIx = (slCount(records)-1) / 2; -char cartVar[512]; -safef(cartVar, sizeof(cartVar), "%s.centerVariantPos", tg->tdb->track); +char *cartVar = centerPosCartVarName(tg->tdb); char *centerPos = cartOptionalString(cart, cartVar); if (centerPos != NULL) { char *words[3]; int wordCount = chopByChar(cloneString(centerPos), ':', words, sizeof(words)); if (wordCount != 2) errAbort("Cart variable %s format error: expected 'chrom:pos', got %s", cartVar, centerPos); if (sameString(chromName, words[0])) { int pos = sqlUnsigned(words[1]); int winSize = seqEnd - seqStart; if (pos > (seqStart - winSize) && pos < (seqEnd + winSize)) { int i; @@ -448,44 +479,37 @@ 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. */ { const struct vcfFile *vcff = tg->extraUiData; if (vcff->records == NULL) return; unsigned short gtHapEnd = 0; int ix, centerIx = getCenterVariantIx(tg, seqStart, seqEnd, vcff->records); unsigned short *gtHapOrder = clusterChroms(vcff, centerIx, >HapEnd); struct vcfRecord *rec, *centerRec = NULL; for (rec = vcff->records, ix=0; rec != NULL; rec = rec->next, ix++) { - drawOneRec(rec, gtHapOrder, gtHapEnd, tg, hvg, xOff, yOff, width); if (ix == centerIx) centerRec = rec; + else + drawOneRec(rec, gtHapOrder, gtHapEnd, tg, hvg, xOff, yOff, width, FALSE); } // Draw the center rec on top, outlined with black lines, to make sure it is very visible: -drawOneRec(centerRec, gtHapOrder, gtHapEnd, tg, hvg, xOff, yOff, width); -const double scale = scaleForPixels(width); -int x1 = round((double)(centerRec->chromStart-winStart)*scale) + xOff; -int x2 = round((double)(centerRec->chromEnd-winStart)*scale) + xOff; -int yBot = yOff + tg->height - 2; -hvGfxBox(hvg, x1-4, yOff, 3, tg->height, color); -hvGfxBox(hvg, x2+2, yOff, 3, tg->height, color); -hvGfxLine(hvg, x1-2, yOff, x2+2, yOff, MG_BLACK); -hvGfxLine(hvg, x1-2, yBot, x2+2, yBot, MG_BLACK); +drawOneRec(centerRec, gtHapOrder, gtHapEnd, tg, hvg, xOff, yOff, width, TRUE); } static int vcfHapClusterTotalHeight(struct track *tg, enum trackVisibility vis) /* Return height of haplotype graph (2 * #samples * lineHeight); * 2 because we're assuming diploid genomes here, no XXY, tetraploid etc. */ { // Should we make it single-height when on chrY? const struct vcfFile *vcff = tg->extraUiData; if (vcff->records == NULL) return 0; int ploidy = 2; tg->height = ploidy * vcff->genotypeCount * tg->lineHeight; return tg->height; }