007cb48e6924935c046a7a0d0354eeac84e5f6cb
angie
  Wed Oct 5 11:30:12 2011 -0700
Feature #3710 (vcfTabix UI options): added filtering by value of FILTER column.
diff --git src/hg/hgTracks/vcfTrack.c src/hg/hgTracks/vcfTrack.c
index 944cedc..e66ff4a 100644
--- src/hg/hgTracks/vcfTrack.c
+++ src/hg/hgTracks/vcfTrack.c
@@ -6,39 +6,68 @@
 #include "errCatch.h"
 #include "hacTree.h"
 #include "hdb.h"
 #include "hgTracks.h"
 #include "pgSnp.h"
 #include "trashDir.h"
 #include "vcf.h"
 #include "vcfUi.h"
 #if (defined USE_TABIX && defined KNETFILE_HOOKS)
 #include "knetUdc.h"
 #include "udc.h"
 #endif//def USE_TABIX && KNETFILE_HOOKS
 
 #ifdef USE_TABIX
 
-static struct pgSnp *vcfFileToPgSnp(struct vcfFile *vcff)
+static boolean getFilterValues(struct trackDb *tdb, struct slName **retValues)
+/* Return TRUE and set retValues if cart contains FILTER column values to exclude */
+{
+char cartVar[512];
+safef(cartVar, sizeof(cartVar), "%s.exclude_filterColumn", tdb->track);
+if (cartListVarExists(cart, cartVar))
+    {
+    struct slName *selectedValues = cartOptionalSlNameList(cart, cartVar);
+    if (retValues != NULL)
+	*retValues = selectedValues;
+    return TRUE;
+    }
+return FALSE;
+}
+
+static boolean excludeRecord(struct vcfRecord *record, struct slName *filterValues)
+/* Return TRUE if record's FILTER column value(s) matches one of filterValues (from cart). */
+{
+int i;
+for (i = 0;  i < record->filterCount;  i++)
+    if (slNameInList(filterValues, record->filters[i]))
+	return TRUE;
+return FALSE;
+}
+
+static struct pgSnp *vcfFileToPgSnp(struct vcfFile *vcff, struct trackDb *tdb)
 /* Convert vcff's records to pgSnp; don't free vcff until you're done with pgSnp
  * because it contains pointers into vcff's records' chrom. */
 {
 struct pgSnp *pgsList = NULL;
 struct vcfRecord *rec;
 int maxLen = 33;
+struct slName *filterValues = NULL;
+boolean gotFilter = getFilterValues(tdb, &filterValues);
 for (rec = vcff->records;  rec != NULL;  rec = rec->next)
     {
+    if (gotFilter && excludeRecord(rec, filterValues))
+	continue;
     struct pgSnp *pgs = pgSnpFromVcfRecord(rec);
     // Insertion sequences can be quite long; abbreviate here for display.
     int len = strlen(pgs->name);
     if (len > maxLen)
 	{
 	if (strchr(pgs->name, '/') != NULL)
 	    {
 	    char *copy = cloneString(pgs->name);
 	    char *allele[8];
 	    int cnt = chopByChar(copy, '/', allele, pgs->alleleCount);
 	    int maxAlLen = maxLen / pgs->alleleCount;
 	    pgs->name[0] = '\0';
 	    int i;
 	    for (i = 0;  i < cnt;  i++)
 		{
@@ -750,31 +779,31 @@
 boolean compositeLevel = isNameAtCompositeLevel(tg->tdb, tg->tdb->track);
 boolean hapClustEnabled = cartUsualBooleanClosestToHome(cart, tg->tdb, compositeLevel,
 							VCF_HAP_ENABLED_VAR, TRUE);
 /* protect against temporary network error */
 struct errCatch *errCatch = errCatchNew();
 if (errCatchStart(errCatch))
     {
     vcff = vcfTabixFileMayOpen(fileOrUrl, chromName, winStart, winEnd, vcfMaxErr);
     if (vcff != NULL)
 	{
 	if (hapClustEnabled && vcff->genotypeCount > 1 && vcff->genotypeCount < 3000 &&
 	    (tg->visibility == tvPack || tg->visibility == tvSquish))
 	    vcfHapClusterOverloadMethods(tg, vcff);
 	else
 	    {
-	    tg->items = vcfFileToPgSnp(vcff);
+	    tg->items = vcfFileToPgSnp(vcff, tg->tdb);
 	    // 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 || vcff == NULL)
     {
     if (isNotEmpty(errCatch->message->string))
 	tg->networkErrMsg = cloneString(errCatch->message->string);
     tg->drawItems = bigDrawWarning;
     tg->totalHeight = bigWarnTotalHeight;
     }
 errCatchFree(&errCatch);