4cab7f311cadce7428c1d7e1c4dfdcb0d3a43033 angie Wed Jul 27 10:32:19 2011 -0700 Feature #3710 (vcfTabix UI options): Added controls for selection of centervariant for haplotype clustering/sorting. Also, some hgc improvements: made the Genotype Details table into a collapsible section; better display of QUAL and FILTER column values, which also involved improving the representation of those columns in src/inc/vcf.h. diff --git src/hg/hgTracks/vcfTrack.c src/hg/hgTracks/vcfTrack.c index 5361607..752d6ae 100644 --- src/hg/hgTracks/vcfTrack.c +++ src/hg/hgTracks/vcfTrack.c @@ -385,38 +385,30 @@ 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, 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; @@ -442,74 +434,69 @@ } 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) + char cartVar[512]; + safef(cartVar, sizeof(cartVar), "%s.centerVariantChrom", tg->tdb->track); + char *centerChrom = cartOptionalString(cart, cartVar); + 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 link below the variant name."); mouseoverText = dy->string; } mapBoxHgcOrHgGene(hvg, rec->chromStart, rec->chromEnd, x1, yOff, w, tg->height, tg->track, 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 = 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]); +char cartVar[512]; +safef(cartVar, sizeof(cartVar), "%s.centerVariantChrom", tg->tdb->track); +char *centerChrom = cartOptionalString(cart, cartVar); +if (centerChrom != NULL && sameString(chromName, centerChrom)) + { + safef(cartVar, sizeof(cartVar), "%s.centerVariantPos", tg->tdb->track); + int centerPos = cartInt(cart, cartVar); int winSize = seqEnd - seqStart; - if (pos > (seqStart - winSize) && pos < (seqEnd + winSize)) + if (centerPos > (seqStart - winSize) && centerPos < (seqEnd + winSize)) { int i; struct vcfRecord *rec; for (rec = records, i = 0; rec != NULL; rec = rec->next, i++) - if (rec->chromStart >= pos) + if (rec->chromStart >= centerPos) return i; return i-1; } } - } return defaultIx; } 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); @@ -575,44 +562,44 @@ { // TODO: may need to handle per-chrom files like bam, maybe fold bamFileNameFromTable into this: struct sqlConnection *conn = hAllocConnTrack(database, tg->tdb); fileOrUrl = bbiNameFromSettingOrTable(tg->tdb, conn, tg->table); hFreeConn(&conn); } int vcfMaxErr = 100; struct vcfFile *vcff = NULL; /* protect against temporary network error */ struct errCatch *errCatch = errCatchNew(); if (errCatchStart(errCatch)) { vcff = vcfTabixFileMayOpen(fileOrUrl, chromName, winStart, winEnd, vcfMaxErr); if (vcff != NULL) { - if (doHapClusterDisplay && vcff->genotypeCount > 0 && vcff->genotypeCount < 3000 && + if (doHapClusterDisplay && vcff->genotypeCount > 1 && vcff->genotypeCount < 3000 && (tg->visibility == tvPack || tg->visibility == tvSquish)) vcfHapClusterOverloadMethods(tg, vcff); else { tg->items = vcfFileToPgSnp(vcff); // pgSnp bases coloring/display decision on count of items: tg->customInt = slCount(tg->items); } // Don't vcfFileFree here -- we are using its string pointers! } } errCatchEnd(errCatch); -if (errCatch->gotError) +if (errCatch->gotError || vcff == NULL) { if (isNotEmpty(errCatch->message->string)) tg->networkErrMsg = cloneString(errCatch->message->string); tg->drawItems = bigDrawWarning; tg->totalHeight = bigWarnTotalHeight; } errCatchFree(&errCatch); } void vcfTabixMethods(struct track *track) /* Methods for VCF + tabix files. */ { pgSnpMethods(track); track->loadItems = vcfTabixLoadItems; track->canPack = TRUE;