601ece4d47e590855e1232bc968593299fc4b703
kate
  Wed Sep 11 11:09:09 2019 -0700
Clean up and expand interactMultiRegion trackDb seetting to specify padding.  Needed for transEqtl  (huge and chross-chrom interactions). refs #24037

diff --git src/hg/hgc/interactClick.c src/hg/hgc/interactClick.c
index a69f1fd..67b4d26 100644
--- src/hg/hgc/interactClick.c
+++ src/hg/hgc/interactClick.c
@@ -145,42 +145,41 @@
             if (differentString(name, inter->sourceName) && differentString(name, inter->targetName))
                 continue;
             }
         }
     minStart = inter->chromStart <  minStart ? inter->chromStart : minStart;
     maxEnd = inter->chromEnd > maxEnd ? inter->chromEnd : maxEnd;
     slAddHead(&filtered, ipr);
     }
 
 *retStart = minStart;
 *retEnd = maxEnd;
 // consider sorting on score or position
 return filtered;
 }
 
-static char *makeInteractRegionFile(char *name, struct interact *inters, char **retCustomText)
+static char *makeInteractRegionFile(char *name, struct interact *inters, int padding, char **retCustomText)
 /* Create bed file in trash directory with end coordinates for multi-region mode,
  * and a custom track for display showing regions */
 {
 struct tempName mrTn;
 trashDirFile(&mrTn, "hgt", "custRgn_interact", ".bed");
 FILE *f = fopen(mrTn.forCgi, "w");
 if (f == NULL)
     errAbort("can't create temp file %s", mrTn.forCgi);
 
 char regionInfo[1024];
-int padding = 200;
 safef(regionInfo, sizeof regionInfo, "#padding %d\n", padding);
 mustWrite(f, regionInfo, strlen(regionInfo));
 
 safef(regionInfo, sizeof regionInfo, "#shortDesc %s\n", name);
 mustWrite(f, regionInfo, strlen(regionInfo));
 
 struct interact *inter = NULL;
 struct bed *region, *regions = NULL;
 struct hash *uniqRegions = hashNew(0);
 
 struct dyString *ds = dyStringNew(0);
 dyStringPrintf(ds, "track name='Multi Regions' description='Interact regions for %s' "
                         "itemRgb=On labelOnFeature=on\n", name);
 for (inter = inters; inter != NULL; inter = inter->next)
     {
@@ -246,51 +245,58 @@
 hexBinaryString(hash, SHA_DIGEST_LENGTH, newSha1, (SHA_DIGEST_LENGTH + 1) * 2);
 char sha1File[1024];
 safef(sha1File, sizeof sha1File, "%s.sha1", mrTn.forCgi);
 f = mustOpen(sha1File, "w");
 mustWrite(f, newSha1, strlen(newSha1));
 carefulClose(&f);
 
 // post custom track
 if (retCustomText != NULL)
     *retCustomText = dyStringCannibalize(&ds);
 
 // return BED filename
 return cloneString(mrTn.forCgi);
 }
 
-static void multiRegionLink(char *name, struct interact *inters)
+static void multiRegionLink(struct trackDb *tdb, char *name, struct interact *inters)
 // Print link to multi-region view of ends if appropriate 
 // (or provide a link to remove if already in this mode) 
 {
+char *setting = trackDbSetting(tdb, "interactMultiRegion");
+if (!setting || sameString(setting, "off"))
+    return;
+int padding = 200;
+if (differentString(setting, "on"))
+    padding = (int)strtol(setting, NULL, 10);
+    
 if (inters->next == NULL && interactEndsOverlap(inters))
     return;
 char *virtShortDesc = cartOptionalString(cart, "virtShortDesc");
 boolean isVirtMode = cartUsualBoolean(cart, "virtMode", FALSE);
 if (isVirtMode && virtShortDesc && sameString(virtShortDesc, name))
     {
     printf("<br>Show interaction%s in "
                 "<a href='hgTracks?"
                     "virtMode=0&"
                     "virtModeType=default'>"
                 " normal browser view</a> (exit multi-region view)",
                         inters->next != NULL ? "s" : "");
     }
 else
     {
     char *customText = NULL;
-    char *regionFile = makeInteractRegionFile(name, inters, &customText);
+    char *regionFile = makeInteractRegionFile(name, inters, padding, &customText);
     printf("<br>Show interaction ends in "
             "<a href='hgTracks?"
                 "virtMode=1&"
                 "virtModeType=customUrl&"
                 "virtWinFull=on&"
                 "virtShortDesc=%s&"
                 "multiRegionsBedUrl=%s&"
                 "%s=%s'>"
             " multi-region browser view </a>(custom region mode)",
                     name, cgiEncode(regionFile),
                     CT_CUSTOM_TEXT_VAR, cgiEncode(customText));
     if (isVirtMode)
         printf(" or "
                 "<a href='hgTracks?"
                     "virtMode=0&"
@@ -370,110 +376,106 @@
 printf("<b>%s region:</b> %s&nbsp;&nbsp;"
                 "<a href='hgTracks?position=%s:%d-%d' target='_blank'>%s:%s-%s</a> %s",
                 region2Label, region2Name, region2Chrom, region2Start+1, region2End,
                 region2Chrom, startBuf, endBuf, 
                 inter->targetStrand[0] == '.' ? "" : inter->targetStrand);
 printf("&nbsp;&nbsp;%s bp<br>\n", sizeBuf);
 int distance = interactRegionDistance(inter);
 if (distance > 0)
     {
     // same chrom
     sprintLongWithCommas(sizeBuf, distance);
     printf("<b>Distance between midpoints:</b> %s bp<br>\n", sizeBuf); 
     }
 }
 
-void doInteractItemDetails(struct trackDb *tdb, struct interactPlusRow *ipr, char *item, 
-                                boolean isMultiple, boolean doMultiRegion)
+void doInteractItemDetails(struct trackDb *tdb, struct interactPlusRow *ipr, char *item, boolean isMultiple)
 /* Details of interaction item */
 {
 struct interact *inter = ipr->interact;
 struct slPair *fields = getFields(tdb, ipr->row);
 printCustomUrlWithFields(tdb, inter->name, inter->name, TRUE, fields);
 if (!isEmptyTextField(inter->name))
     printf("<b>Interaction:</b> %s<br>\n", inter->name);
 printf("<b>Score:</b> %d<br>\n", inter->score);
 printf("<b>Value:</b> %0.3f<br>\n", inter->value);
 if (!isEmptyTextField(inter->exp))
     printf("<b>Experiment:</b> %s<br>\n", inter->exp);
 puts("<p>");
 if (!isMultiple)
     {
     doInteractRegionDetails(tdb, inter);
-    if (doMultiRegion)
-        multiRegionLink(inter->name, inter);
+    multiRegionLink(tdb, inter->name, inter);
     }
 }
 
 static struct interact *iprsToInters(struct interactPlusRow *iprs)
 /* Create list of interacts from interactPlusRows */
 {
 struct interactPlusRow *ipr;
 struct interact *inters = NULL;
 for (ipr = iprs; ipr != NULL; ipr = ipr->next)
     slAddHead(&inters, ipr->interact);
 return inters;
 }
 
 void doInteractDetails(struct trackDb *tdb, char *item)
 /* Details of interaction items */
 {
 char *chrom = cartString(cart, "c");
 int start = cartInt(cart, "o");
 int end = cartInt(cart, "t");
 char *foot = cgiOptionalString("foot");
-boolean doMultiRegion = trackDbSettingOn(tdb, "interactMultiRegion");
+
 int minStart, maxEnd;
 struct interactPlusRow *iprs = getInteractions(tdb, chrom, start, end, item, foot, &minStart, &maxEnd);
 start = minStart;
 end = maxEnd;
 if (iprs == NULL)
     errAbort("Can't find interaction %s", item ? item : "");
 int count = slCount(iprs);
 char *clusterMode = interactUiClusterMode(cart, tdb->track, tdb);
 if (count > 1 || clusterMode)
     {
     printf("<b>Interactions:</b> %d<p>", count);
     struct interact *inters = iprsToInters(iprs);
     if (clusterMode || foot)
         {
         char startBuf[1024], endBuf[1024], sizeBuf[1024];
         sprintLongWithCommas(startBuf, start + 1);
         sprintLongWithCommas(endBuf, end);
         sprintLongWithCommas(sizeBuf, end - start + 1);
         printf("<b>%s interactions region:</b> &nbsp;&nbsp;"
                         "<a href='hgTracks?position=%s:%d-%d' target='_blank'>%s:%s-%s</a> ",
                         item, chrom, start+1, end, chrom, startBuf, endBuf);
         printf("&nbsp;&nbsp;%s bp<br>\n", sizeBuf);
         }
     else
         {
         // overlapping items, same start/end/name
         doInteractRegionDetails(tdb, inters);
         }
-    if (doMultiRegion)
-        multiRegionLink(item, inters);
+    multiRegionLink(tdb, item, inters);
     printf("</p>");
     }
 
 //genericHeader(tdb, item);
 static struct interactPlusRow *ipr = NULL;
 for (ipr = iprs; ipr != NULL; ipr = ipr->next)
     {
     if (count > 1)
         printf("<hr>\n");
-    doInteractItemDetails(tdb, ipr, item, count > 1, doMultiRegion);
+    doInteractItemDetails(tdb, ipr, item, count > 1);
     if (foot || (clusterMode && count > 1))
         {
         struct interact *inter = ipr->interact;
         // just one interact (we have these in list for handling clusters earlier)
         inter->next = NULL;
         doInteractRegionDetails(tdb, inter);
-        if (doMultiRegion)
-            multiRegionLink(inter->name, inter);
+        multiRegionLink(tdb, inter->name, inter);
         }
     if (count > 1 && !isEmptyTextField(ipr->interact->name) && sameString(ipr->interact->name, item))
         printf("<hr>\n");
     }
 }