8c86cfcdfb9447faf474101662d0c846dfa25981 kate Wed Sep 4 17:23:18 2019 -0700 Interact track multi-region link now adds a custom track showing where multi-regions are located. refs #22422 diff --git src/hg/hgc/interactClick.c src/hg/hgc/interactClick.c index 772c9ed..a69f1fd 100644 --- src/hg/hgc/interactClick.c +++ src/hg/hgc/interactClick.c @@ -1,25 +1,26 @@ /* Details page for interact type tracks */ /* Copyright (C) 2018 The Regents of the University of California * See README in this or parent directory for licensing information. */ #include "common.h" #include "obscure.h" #include "hdb.h" #include "jksql.h" #include "hgc.h" +#include "customTrack.h" #include "trashDir.h" #include "hex.h" #include <openssl/sha.h> #include "interact.h" #include "interactUi.h" struct interactPlusRow { /* Keep field values in string format, for url processing */ struct interactPlusRow *next; struct interact *interact; char **row; }; @@ -144,136 +145,163 @@ 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) -/* Create bed file in trash directory with end coordinates for multi-region mode */ +static char *makeInteractRegionFile(char *name, struct interact *inters, 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)); -//warn("%s", regionInfo); safef(regionInfo, sizeof regionInfo, "#shortDesc %s\n", name); mustWrite(f, regionInfo, strlen(regionInfo)); -//warn("%s", 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) { char buf[256]; - //safef(buf, sizeof buf, "%s:%d-%d", region1->chrom, region1->chromStart, region1->chromEnd); safef(buf, sizeof buf, "%s:%d-%d", inter->sourceChrom, inter->sourceStart, inter->sourceEnd); if (!hashLookup(uniqRegions, buf)) { hashAdd(uniqRegions, cloneString(buf), NULL); AllocVar(region); region->chrom = inter->sourceChrom; region->chromStart = inter->sourceStart; region->chromEnd = inter->sourceEnd; slAddHead(®ions, region); } safef(buf, sizeof buf, "%s:%d-%d", inter->targetChrom, inter->targetStart, inter->targetEnd); if (!hashLookup(uniqRegions, buf)) { hashAdd(uniqRegions, cloneString(buf), NULL); AllocVar(region); region->chrom = inter->targetChrom; region->chromStart = inter->targetStart; region->chromEnd = inter->targetEnd; slAddHead(®ions, region); } } slSort(®ions, bedCmp); struct bed *prevRegion = NULL; + +// alternate item colors +char *colorLight = "184,201,255"; +char *colorDark = "0,0,0"; +boolean doLightColor = TRUE; + +// print regions to BED file and custom track for (region = regions; region != NULL; region = region->next) { // filter out nested regions if (prevRegion == NULL || differentString(region->chrom, prevRegion->chrom) || region->chromStart >= prevRegion->chromEnd) { safef(regionInfo, sizeof regionInfo, "%s\t%d\t%d\n", region->chrom, region->chromStart, region->chromEnd); mustWrite(f, regionInfo, strlen(regionInfo)); + int start = max(region->chromStart - padding, 0); + int end = min(region->chromEnd + padding, hChromSize(database, region->chrom)); + char *color = doLightColor ? colorLight : colorDark; + doLightColor = !doLightColor; + dyStringPrintf(ds, "%s\t%d\t%d\t" + "%s:%d+%d_bp\t" + "0\t.\t%d\t%d\t%s\n", + region->chrom, start, end, + region->chrom, start+1, end-start, + start, end, color); } prevRegion = region; } fclose(f); // create SHA1 file; used to see if file has changed unsigned char hash[SHA_DIGEST_LENGTH]; SHA1((const unsigned char *)regionInfo, strlen(regionInfo), hash); char newSha1[(SHA_DIGEST_LENGTH + 1) * 2]; 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) // Print link to multi-region view of ends if appropriate // (or provide a link to remove if already in this mode) { if (inters->next == NULL && interactEndsOverlap(inters)) return; char *virtShortDesc = cartOptionalString(cart, "virtShortDesc"); boolean isVirtMode = cartUsualBoolean(cart, "virtMode", FALSE); -//warn("virtShortDesc: %s, name: %s", virtShortDesc, name); 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 *regionFile = makeInteractRegionFile(name, inters); - //warn("regionFile: %s", regionFile); + char *customText = NULL; + char *regionFile = makeInteractRegionFile(name, inters, &customText); printf("<br>Show interaction ends in " "<a href='hgTracks?" "virtMode=1&" "virtModeType=customUrl&" "virtWinFull=on&" "virtShortDesc=%s&" - "multiRegionsBedUrl=%s'>" + "multiRegionsBedUrl=%s&" + "%s=%s'>" " multi-region browser view </a>(custom region mode)", - name, cgiEncode(regionFile)); + name, cgiEncode(regionFile), + CT_CUSTOM_TEXT_VAR, cgiEncode(customText)); if (isVirtMode) printf(" or " "<a href='hgTracks?" "virtMode=0&" "virtModeType=default'>" " normal browser view</a>"); } printf(" "); printf("<a href=\"../goldenPath/help/multiRegionHelp.html\" target=_blank>(Help)</a>\n"); } void doInteractRegionDetails(struct trackDb *tdb, struct interact *inter) { /* print info for both regions */ /* Use different labels: