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, &gtHapEnd);
@@ -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;