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 " "<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(" %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> " "<a href='hgTracks?position=%s:%d-%d' target='_blank'>%s:%s-%s</a> ", item, chrom, start+1, end, chrom, startBuf, endBuf); printf(" %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"); } }