ff297774c7e9cb7056b780ea5554dc1ad2e22c10
braney
  Wed Aug 1 12:57:43 2018 -0700
add regular expression filtering on bigBeds.

diff --git src/hg/hgTracks/bigBedTrack.c src/hg/hgTracks/bigBedTrack.c
index 0c81fe7..daf5482 100644
--- src/hg/hgTracks/bigBedTrack.c
+++ src/hg/hgTracks/bigBedTrack.c
@@ -117,30 +117,44 @@
             {
             ret->comparisonType = COMPARE_LESS;
             ret->value1 = max;
             }
         else
             {
             ret->comparisonType = COMPARE_BETWEEN;
             ret->value1 = min;
             ret->value2 = max;
             }
         }
     }
 return ret;
 }
 
+struct bigBedFilter *bigBedMakeFilterText(struct cart *cart, struct bbiFile *bbi, struct trackDb *tdb, char *filterName, char *field)
+/* Add a bigBed filter using a trackDb filterText statement. */
+{
+struct bigBedFilter *filter;
+char *setting = trackDbSettingClosestToHome(tdb, filterName);
+char *value = cartUsualStringClosestToHome(cart, tdb, FALSE, filterName, setting);
+
+AllocVar(filter);
+filter->fieldNum =  bbExtraFieldIndex(bbi, field) + 3;
+filter->comparisonType = COMPARE_REGEXP;
+regcomp(&filter->regEx, value, REG_NOSUB);
+
+return filter;
+}
 
 struct bigBedFilter *bigBedMakeFilterBy(struct cart *cart, struct bbiFile *bbi, struct trackDb *tdb, char *field, struct slName *choices)
 /* Add a bigBed filter using a trackDb filterBy statement. */
 {
 struct bigBedFilter *filter;
 
 AllocVar(filter);
 filter->fieldNum =  bbExtraFieldIndex(bbi, field) + 3;
 filter->comparisonType = COMPARE_HASH;
 filter->valueHash = newHash(5);
 
 for(; choices; choices = choices->next)
     hashStore(filter->valueHash, choices->name);
 
 return filter;
@@ -148,55 +162,69 @@
 
 struct bigBedFilter *bigBedBuildFilters(struct cart *cart, struct bbiFile *bbi, struct trackDb *tdb)
 /* Build all the numeric and filterBy filters for a bigBed */
 {
 struct bigBedFilter *filters = NULL, *filter;
 struct slName *filterSettings = trackDbSettingsWildMatch(tdb, "*Filter");
 
 for(; filterSettings; filterSettings = filterSettings->next)
     {
     char *fieldName = cloneString(filterSettings->name);
     fieldName[strlen(fieldName) - sizeof "Filter" + 1] = 0;
     if ((filter = bigBedMakeNumberFilter(cart, bbi, tdb, filterSettings->name, NULL, fieldName)) != NULL)
         slAddHead(&filters, filter);
     }
 
+filterSettings = trackDbSettingsWildMatch(tdb, "*FilterText");
+
+for(; filterSettings; filterSettings = filterSettings->next)
+    {
+    char *fieldName = cloneString(filterSettings->name);
+    fieldName[strlen(fieldName) - sizeof "FilterText" + 1] = 0;
+    if ((filter = bigBedMakeFilterText(cart, bbi, tdb, filterSettings->name,  fieldName)) != NULL)
+        slAddHead(&filters, filter);
+    }
+
 filterBy_t *filterBySet = filterBySetGet(tdb, cart,NULL);
 filterBy_t *filterBy = filterBySet;
 for (;filterBy != NULL; filterBy = filterBy->next)
     {
     if (filterBy->slChoices && differentString(filterBy->slChoices->name, "All")) 
         {
         if ((filter = bigBedMakeFilterBy(cart, bbi, tdb, filterBy->column, filterBy->slChoices)) != NULL)
             slAddHead(&filters, filter);
         }
     }
 
 return filters;
 }
 
 
 boolean bigBedFilterInterval(char **bedRow, struct bigBedFilter *filters)
 /* Go through a row and filter based on filters.  Return TRUE if all filters are passed. */
 {
 struct bigBedFilter *filter;
 for(filter = filters; filter; filter = filter->next)
     {
     double val = atof(bedRow[filter->fieldNum]);
 
     switch(filter->comparisonType)
         {
+        case COMPARE_REGEXP:
+            if (regexec(&filter->regEx,bedRow[filter->fieldNum], 0, NULL,0 ) != 0)
+                return FALSE;
+            break;
         case COMPARE_HASH:
             if (!hashLookup(filter->valueHash, bedRow[filter->fieldNum]))
                 return FALSE;
             break;
         case COMPARE_LESS:
             if (!(val <= filter->value1))
                 return FALSE;
             break;
         case COMPARE_MORE:
             if (!(val >= filter->value1))
                 return FALSE;
             break;
         case COMPARE_BETWEEN:
             if (!((val >= filter->value1) && (val <= filter->value2)))
                 return FALSE;