491395482b817cfe82cbdef4dd7f8ee0723c1a4a
angie
  Wed Mar 23 21:01:49 2011 -0700
Feature #2822, #2823 (VCF customFactory + track handler):Added a new track type, vcfTabix, with handlers in hgTracks and hgc
and a customFactory.  It is a new bigDataUrl type of track; the
remote VCF file must be compressed and indexed by tabix, so like
BAM a separate index file is required.  If the VCF file has
genotypes, then each sample's two haplotypes are graphed in a
line, with one line per sample.  Otherwise, alleles and counts
(if available) are drawn using Belinda's pgSnp methods.
The source code has to be compiled with USE_TABIX=1 (which is
automatically set for us by common.mk when it finds the local
installation) in order for the CGIs to recognize the track type.

diff --git src/hg/hgTracks/simpleTracks.c src/hg/hgTracks/simpleTracks.c
index 459ce1a..65d67e1 100644
--- src/hg/hgTracks/simpleTracks.c
+++ src/hg/hgTracks/simpleTracks.c
@@ -9857,30 +9857,32 @@
 if (differentString(el->alleleFreq, ""))
     chopByChar(cntCopy, ',', freq, el->alleleCount);
 
 for (i=0; i < el->alleleCount; i++)
     {
     if (sameString(el->alleleFreq, "") || sameString(freq[i], "0"))
         freq[i] = "?";
     dyStringPrintf(ds, "%s:%s ", all[i], freq[i]);
     }
 mapBoxHgcOrHgGene(hvg, start, end, x, y, width, height, tg->track,
                   mapItemName, ds->string, directUrl, withHgsid, NULL);
 freeDyString(&ds);
 }
 
 void pgSnpMethods (struct track *tg)
+/* Personal Genome SNPs: show two alleles with stacked color bars for base alleles and
+ * (if available) allele counts in mouseover. */
 {
 bedMethods(tg);
 tg->loadItems = loadPgSnp;
 tg->freeItems = freePgSnp;
 tg->totalHeight = pgSnpHeight;
 tg->itemName = pgSnpName;
 tg->drawItemAt = pgSnpDrawAt;
 tg->mapItem = pgSnpMapItem;
 tg->nextItemButtonable = TRUE;
 tg->nextPrevItem = linkedFeaturesLabelNextPrevItem;
 }
 
 void loadBlatz(struct track *tg)
 {
 enum trackVisibility vis = tg->visibility;
@@ -12184,30 +12186,76 @@
 
 void remoteMethods(struct track *tg)
 {
 tg->freeItems = remoteFreeItems;
 tg->loadItems = remoteLoadItems;
 tg->drawItems = remoteDrawItems;
 tg->itemName = remoteName;
 tg->lineHeight = 10;
 tg->totalHeight = tgFixedTotalHeightNoOverflow;
 tg->itemHeight = tgFixedItemHeight;
 tg->itemStart = tgItemNoStart;
 tg->itemEnd = tgItemNoEnd;
 tg->mapItemName = remoteName;
 }
 
+static void drawExampleMessageLine(struct track *tg, int seqStart, int seqEnd, struct hvGfx *hvg,
+				   int xOff, int yOff, int width, MgFont *font, Color color,
+				   enum trackVisibility vis)
+/* Example, meant to be overloaded: draw a message in place of track items. */
+{
+char message[512];
+safef(message, sizeof(message), "drawExampleMessageLine: copy me and put your own message here.");
+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 messageLineMethods(struct track *track)
+/* Methods for drawing a single-height message line instead of track items,
+ * e.g. if source was compiled without a necessary library. */
+{
+linkedFeaturesMethods(track);
+track->loadItems = dontLoadItems;
+track->drawItems = drawExampleMessageLine;
+// Following few lines taken from hgTracks.c getTrackList, because this is called earlier
+// but needs to know track vis from tdb+cart:
+char *s = cartOptionalString(cart, track->track);
+if (cgiOptionalString("hideTracks"))
+    {
+    s = cgiOptionalString(track->track);
+    if (s != NULL && (hTvFromString(s) != track->tdb->visibility))
+	{
+	cartSetString(cart, track->track, s);
+	}
+    }
+// end stuff copied from hgTracks.c
+enum trackVisibility trackVis = track->tdb->visibility;
+if (s != NULL)
+    trackVis = hTvFromString(s);
+if (trackVis != tvHide)
+    {
+    track->visibility = tvDense;
+    track->limitedVis = tvDense;
+    track->limitedVisSet = TRUE;
+    }
+track->nextItemButtonable = track->nextExonButtonable = FALSE;
+track->nextPrevItem = NULL;
+track->nextPrevExon = NULL;
+}
+
+
 void fillInFromType(struct track *track, struct trackDb *tdb)
 /* Fill in various function pointers in track from type field of tdb. */
 {
 char *typeLine = tdb->type, *words[8], *type;
 int wordCount;
 if (typeLine == NULL)
     return;
 wordCount = chopLine(cloneString(typeLine), words);
 if (wordCount <= 0)
     return;
 type = words[0];
 
 #ifndef GBROWSE
 if (sameWord(type, "bed"))
     {
@@ -12286,30 +12334,36 @@
     }
 else if (sameWord(type, "netAlign"))
     {
     netMethods(track);
     }
 else if (sameWord(type, "maf"))
     {
     mafMethods(track);
     }
 else if (sameWord(type, "bam"))
     {
     bamMethods(track);
     if (trackShouldUseAjaxRetrieval(track))
         track->loadItems = dontLoadItems;
     }
+else if (sameWord(type, "vcfTabix"))
+    {
+    vcfTabixMethods(track);
+    if (trackShouldUseAjaxRetrieval(track))
+        track->loadItems = dontLoadItems;
+    }
 else if (startsWith(type, "bedDetail"))
     {
     bedDetailMethods(track);
     }
 else if (sameWord(type, "pgSnp"))
     {
     pgSnpCtMethods(track);
     }
 #ifndef GBROWSE
 else if (sameWord(type, "coloredExon"))
     {
     coloredExonMethods(track);
     }
 else if (sameWord(type, "axt"))
     {