f0d365eee2b10118a7e32b4ec1bf530f7cf7a576
angie
  Wed Jun 25 16:21:39 2014 -0700
Adding regulatory region to the functional role filter options.Thanks Jonathan for noticing that I forgot to do that!
refs #11461

diff --git src/hg/hgVai/hgVai.c src/hg/hgVai/hgVai.c
index 75401da..f80314c 100644
--- src/hg/hgVai/hgVai.c
+++ src/hg/hgVai/hgVai.c
@@ -857,30 +857,37 @@
 printf("in transcript already subject to nonsense-mediated decay (NMD)<BR>\n");
 cartMakeCheckBox(cart, "hgva_include_exonLoss", TRUE);
 printf("exon loss caused by deletion<BR>\n");
 cartMakeCheckBox(cart, "hgva_include_utr", TRUE);
 printf("5' or 3' UTR<BR>\n");
 cartMakeCheckBox(cart, "hgva_include_cdsSyn", TRUE);
 printf("CDS - synonymous coding change<BR>\n");
 cartMakeCheckBox(cart, "hgva_include_cdsNonSyn", TRUE);
 printf("CDS - non-synonymous (missense, stop gain/loss, frameshift etc)<BR>\n");
 cartMakeCheckBox(cart, "hgva_include_intron", TRUE);
 printf("intron<BR>\n");
 cartMakeCheckBox(cart, "hgva_include_splice", TRUE);
 printf("splice site or splice region<BR>\n");
 cartMakeCheckBox(cart, "hgva_include_nonCodingExon", TRUE);
 printf("exon of non-coding gene<BR>\n");
+struct slRef *regTrackRefList = findRegulatoryTracks();
+if (regTrackRefList != NULL)
+    {
+    cartMakeCheckBox(cart, "hgva_include_regulatory", TRUE);
+    printf("regulatory element (note: these are detected only if one or more tracks "
+	   "are selected in Regulatory regions above)<BR>\n");
+    }
 puts("<BR>");
 endCollapsibleSection();
 }
 
 void selectFiltersKnownVar()
 /* Options to restrict output based on overlap with known variants. */
 {
 boolean gotCommon = findSnpBed4("Common", NULL, NULL);
 boolean gotMult = findSnpBed4("Mult", NULL, NULL);
 if (!gotCommon && !gotMult)
     return;
 startCollapsibleSection("filtersVar", "Known variation", FALSE);
 if (gotMult)
     {
     cartMakeCheckBox(cart, "hgva_include_snpMult", TRUE);
@@ -1347,33 +1354,35 @@
     char *filterName = hel->name;
     struct slName *valList = hel->val;
 //#*** Need a much better way to dispatch...
     if (sameString("factorSource", tdb->type))
 	factorSourceGratorAddFilter(grator, filterName, valList);
     else if (startsWith("bed 5", tdb->type))
 	bed5AddFilter(grator, filterName, valList);
     else
 	dyStringPrintf(dyInfo, "Ignoring %s filter %s\n", tdb->track, filterName);
     }
 hashFree(&varHash);
 }
 
 void addOutputTracks(struct annoGrator **pGratorList, struct hash *gratorsByName,
 		     struct annoFormatter *vepOut, struct annoAssembly *assembly, char *chrom,
-		     boolean doHtml)
+		     boolean doHtml, boolean *retHasRegulatory)
 // Construct grators for tracks selected to appear in EXTRAS column
 {
+boolean includeReg = cartUsualBoolean(cart, "hgva_include_regulatory", TRUE);
+boolean haveReg = FALSE;
 char trackPrefix[128];
 safef(trackPrefix, sizeof(trackPrefix), "hgva_track_%s_", database);
 int trackPrefixLen = strlen(trackPrefix);
 struct slPair *trackVar, *trackVars = cartVarsWithPrefix(cart, trackPrefix);
 for (trackVar = trackVars;  trackVar != NULL;  trackVar = trackVar->next)
     {
     char *val = trackVar->val;
     if (! (sameWord(val, "on") || atoi(val) > 0))
 	continue;
     char *trackName = trackVar->name + trackPrefixLen;
     if (sameString(trackName, "dbNsfpPolyPhen2"))
 	// PolyPhen2 must have a suffix now -- skip obsolete cartVar from existing carts
 	continue;
     struct annoGrator *grator = hashFindVal(gratorsByName, trackName);
     if (grator != NULL)
@@ -1397,37 +1406,40 @@
 	{
 	struct trackDb *tdb = tdbForTrack(database, trackName, &fullTrackList);
 	if (tdb != NULL)
 	    {
 	    grator = gratorFromTrackDb(assembly, tdb->table, tdb, chrom, NO_MAXROWS, NULL,
 				       agoNoConstraint);
 	    if (grator != NULL)
 		{
 		//#*** Need something more sophisticated but this works for our
 		//#*** limited selection of extra tracks:
 		if (asColumnFind(grator->streamer.asObj, "name") != NULL)
 		    column = "name";
 		addFiltersToGrator(grator, tdb);
 		}
 	    description = tdb->longLabel;
-	    isReg = isRegulatoryTrack(tdb, NULL);
+	    isReg = includeReg && isRegulatoryTrack(tdb, NULL);
 	    }
 	}
+    haveReg |= isReg;
     updateGratorListAndVepExtra(grator, pGratorList, vepOut, subset, column, description, isReg);
     if (grator != NULL)
 	hashAdd(gratorsByName, trackName, grator);
     }
+if (retHasRegulatory)
+    *retHasRegulatory = haveReg;
 }
 
 void addFilterTracks(struct annoGrator **pGratorList, struct hash *gratorsByName,
 		     struct annoAssembly *assembly, char *chrom)
 // Add grators for filters (not added to vepOut):
 {
 if (!cartUsualBoolean(cart, "hgva_include_snpCommon", TRUE))
     {
     struct annoGrator *grator = gratorForSnpBed4(gratorsByName, "Common", assembly, chrom,
 						 agoMustNotOverlap, NULL);
     updateGratorList(grator, pGratorList);
     }
 
 if (!cartUsualBoolean(cart, "hgva_include_snpMult", TRUE))
     {
@@ -2079,30 +2091,38 @@
  * (main page will be displayed) */
 {
 struct trackDb *varTdb = tdbForTrack(database, variantTrack, &fullTrackList);
 if (varTdb == NULL)
     {
     if (isHubTrack(variantTrack))
 	warn("Can't find hub track '%s'", variantTrack);
     else
 	warn("Can't find tdb for variant track '%s'", variantTrack);
     }
 else
     checkVariantTrack(varTdb);
 return varTdb;
 }
 
+static void adjustGpVarOverlapRule(struct annoGrator *gpVarGrator, boolean haveRegulatory)
+/* If we're able to detect regulatory elements, and want to keep those annotations, loosen up
+ * gpVarGrator's overlap rule from the default (must overlap). */
+{
+if (haveRegulatory && cartUsualBoolean(cart, "hgva_include_regulatory", TRUE))
+    gpVarGrator->setOverlapRule(gpVarGrator, agoNoConstraint);
+}
+
 void doQuery()
 /* Translate simple form inputs into anno* components and execute query. */
 {
 dyInfo = dyStringNew(0);
 char *chrom = NULL;
 uint start = 0, end = 0;
 if (sameString(regionType, hgvaRegionTypeRange))
     getCartPosOrDie(&chrom, &start, &end);
 struct annoAssembly *assembly = getAnnoAssembly(database);
 
 char *geneTrack = cartString(cart, "hgva_geneTrack");
 struct trackDb *geneTdb = tdbForTrack(database, geneTrack, &fullTrackList);
 if (geneTdb == NULL)
     {
     warn("Can't find tdb for gene track %s", geneTrack);
@@ -2163,31 +2183,34 @@
 slAddHead(&gratorList, gpVarGrator);
 if (snpGrator != NULL)
     slAddHead(&gratorList, snpGrator);
 
 // Text or HTML output?
 char *outFormat = cartUsualString(cart, "hgva_outFormat", "vepTab");
 boolean doHtml = sameString(outFormat, "vepHtml");
 
 // Initialize VEP formatter:
 struct annoFormatter *vepOut = annoFormatVepNew("stdout", doHtml,
 						primary, primaryLongLabel,
 						(struct annoStreamer *)gpVarGrator,
 						geneTdb->longLabel,
 						(struct annoStreamer *)snpGrator,
 						snpDesc, assembly);
-addOutputTracks(&gratorList, gratorsByName, vepOut, assembly, chrom, doHtml);
+boolean haveRegulatory = FALSE;
+addOutputTracks(&gratorList, gratorsByName, vepOut, assembly, chrom, doHtml, &haveRegulatory);
+adjustGpVarOverlapRule(gpVarGrator, haveRegulatory);
+
 addFilterTracks(&gratorList, gratorsByName, assembly, chrom);
 
 slReverse(&gratorList);
 
 if (doHtml)
     {
     webStart(cart, database, "Annotated Variants in VEP/HTML format");
     }
 else
     {
     // Undo the htmlPushEarlyHandlers() because after this point they make ugly text:
     popWarnHandler();
     popAbortHandler();
     textOpen();
     webStartText();