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/hgTracks.c src/hg/hgTracks/hgTracks.c
index 71c5aee..7891b7b 100644
--- src/hg/hgTracks/hgTracks.c
+++ src/hg/hgTracks/hgTracks.c
@@ -391,35 +391,32 @@
 hPrintf("<FONT SIZE=1><BR></FONT>\n");
 }
 
 #ifdef REMOTE_TRACK_AJAX_CALLBACK
 static boolean trackUsesRemoteData(struct track *track)
 /* returns TRUE is this track has a remote datasource */
 {
 if (!IS_KNOWN(track->remoteDataSource))
     {
     SET_TO_NO(track->remoteDataSource);
     //if (track->bbiFile != NULL)   // FIXME: Chicken or the egg.  bigWig/bigBed "bbiFile" filled in by loadItems, but we don't want to load items.
     //    {
     //    if (!startsWith("/gbdb/",track->bbiFile->fileName))
     //        SET_TO_YES(track->remoteDataSource);
     //    }
-    if (startsWithWord("bigWig",track->tdb->type) || startsWithWord("bigBed",track->tdb->type))
-        {
-        SET_TO_YES(track->remoteDataSource);
-        }
-    else if (startsWithWord("bam",track->tdb->type))
+    if (startsWithWord("bigWig",track->tdb->type) || startsWithWord("bigBed",track->tdb->type) ||
+	startsWithWord("bam",track->tdb->type) || startsWithWord("vcfTabix", track->tdb->type))
         {
         SET_TO_YES(track->remoteDataSource);
         }
     }
 return IS_YES(track->remoteDataSource);
 }
 
 boolean trackShouldUseAjaxRetrieval(struct track *track)
 /* Tracks with remote data sources should berendered via an ajax callback */
 {
 return (theImgBox && !trackImgOnly && trackUsesRemoteData(track));
 }
 #endif///def REMOTE_TRACK_AJAX_CALLBACK
 
 static int trackPlusLabelHeight(struct track *track, int fontHeight)
@@ -2949,35 +2946,35 @@
 	    {
 	    lfs = lfsFromColoredExonBed(bed);
 	    slAddHead(&lfsList, lfs);
 	    }
 	}
     }
 slReverse(&lfsList);
 slSort(&lfsList, linkedFeaturesSeriesCmp);
 tg->items = lfsList;
 }
 
 char *ctMapItemName(struct track *tg, void *item)
 /* Return composite item name for custom tracks. */
 {
 char *itemName = tg->itemName(tg, item);
-static char buf[256];
+static char buf[512];
 if (strlen(itemName) > 0)
-  sprintf(buf, "%s %s", ctFileName, itemName);
+    safef(buf, sizeof(buf), "%s %s", ctFileName, itemName);
 else
-  sprintf(buf, "%s NoItemName", ctFileName);
+    safef(buf, sizeof(buf), "%s NoItemName", ctFileName);
 return buf;
 }
 
 
 void coloredExonMethodsFromCt(struct track *tg)
 /* same as coloredExonMethods but different loader. */
 {
 linkedFeaturesSeriesMethods(tg);
 tg->loadItems = ctLoadColoredExon;
 tg->canPack = TRUE;
 }
 
 void dontLoadItems(struct track *tg)
 /* No-op loadItems when we aren't going to try. */
 {
@@ -3131,30 +3128,39 @@
     {
     tg = trackFromTrackDb(tdb);
     tg->customPt = ct;
     bamMethods(tg);
     if (trackShouldUseAjaxRetrieval(tg))
         tg->loadItems = dontLoadItems;
     tg->mapItemName = ctMapItemName;
     hashAdd(tdb->settingsHash, BASE_COLOR_USE_SEQUENCE, cloneString("lfExtra"));
     hashAdd(tdb->settingsHash, BASE_COLOR_DEFAULT, cloneString("diffBases"));
     hashAdd(tdb->settingsHash, SHOW_DIFF_BASES_ALL_SCALES, cloneString("."));
     hashAdd(tdb->settingsHash, INDEL_DOUBLE_INSERT, cloneString("on"));
     hashAdd(tdb->settingsHash, INDEL_QUERY_INSERT, cloneString("on"));
     hashAdd(tdb->settingsHash, INDEL_POLY_A, cloneString("on"));
     hashAdd(tdb->settingsHash, "showDiffBasesMaxZoom", cloneString("100"));
     }
+else if (sameString(type, "vcfTabix"))
+    {
+    tg = trackFromTrackDb(tdb);
+    tg->customPt = ct;
+    vcfTabixMethods(tg);
+    if (trackShouldUseAjaxRetrieval(tg))
+        tg->loadItems = dontLoadItems;
+    tg->mapItemName = ctMapItemName;
+    }
 else if (sameString(type, "makeItems"))
     {
     tg = trackFromTrackDb(tdb);
     makeItemsMethods(tg);
     tg->nextItemButtonable = TRUE;
     tg->customPt = ct;
     }
 else if (sameString(type, "bedDetail"))
     {
     tg = trackFromTrackDb(tdb);
     bedDetailCtMethods(tg, ct);
     tg->mapItemName = ctMapItemName; /* must be here to see ctMapItemName */
     }
 else if (sameString(type, "pgSnp"))
     {