7b7d273fd3aeee222d5ee8540298ac6dee662605 kate Wed Sep 13 11:45:23 2017 -0700 Add UI setting to toggle display of tissue color patches (for single-tissue eQTL's. It can be distracting in large regions. refs #15646 diff --git src/hg/hgTracks/gtexEqtlClusterTrack.c src/hg/hgTracks/gtexEqtlClusterTrack.c index 422bfad..bbdf2a8 100644 --- src/hg/hgTracks/gtexEqtlClusterTrack.c +++ src/hg/hgTracks/gtexEqtlClusterTrack.c @@ -4,30 +4,31 @@ * See README in this or parent directory for licensing information. */ #include "common.h" #include "dystring.h" #include "hgTracks.h" #include "gtexInfo.h" #include "gtexTissue.h" #include "gtexUi.h" #include "gtexEqtlCluster.h" struct gtexEqtlClusterTrack /* Track info for filtering (maybe later for draw, map) */ { struct gtexTissue *tissues; /* Tissue names, descriptions */ struct hash *tissueHash; /* Tissue info, keyed by UCSC name, filtered by UI */ + boolean doTissueColor; /* Display tissue color (for single-tissue eQTL's) */ double minEffect; /* Effect size filter (abs value) */ double minProb; /* Probability filter */ }; /* Utility functions */ static struct gtexEqtlCluster *loadOne(char **row) /* Load up gtexEqtlCluster from array of strings. */ { return gtexEqtlClusterLoad(row); } static boolean filterTissuesFromCart(struct track *track, struct gtexEqtlClusterTrack *extras) /* Check cart for tissue selection. Populate track tissues hash */ { @@ -150,48 +151,52 @@ } struct dyString *ds = dyStringNew(0); dyStringPrintf(ds, "%d tissues", ct); return dyStringCannibalize(&ds); } /* Track methods */ static void gtexEqtlClusterLoadItems(struct track *track) /* Load items in window and prune those that don't pass filter */ { /* initialize track info */ struct gtexEqtlClusterTrack *extras; AllocVar(extras); track->extraUiData = extras; +char cartVar[64]; + +// UI settings +safef(cartVar, sizeof cartVar, "%s.%s", track->track, GTEX_EQTL_TISSUE_COLOR); +extras->doTissueColor = cartUsualBoolean(cart, cartVar, GTEX_EQTL_TISSUE_COLOR_DEFAULT); // filter by gene via SQL -char cartVar[64]; safef(cartVar, sizeof cartVar, "%s.%s", track->track, GTEX_EQTL_GENE); char *gene = cartNonemptyString(cart, cartVar); char *where = NULL; if (gene) { struct dyString *ds = dyStringNew(0); sqlDyStringPrintfFrag(ds, "%s = '%s'", GTEX_EQTL_GENE_FIELD, gene); where = dyStringCannibalize(&ds); } bedLoadItemWhere(track, track->table, where, (ItemLoader)loadOne); safef(cartVar, sizeof cartVar, "%s.%s", track->track, GTEX_EQTL_EFFECT); extras->minEffect = fabs(cartUsualDouble(cart, cartVar, GTEX_EFFECT_MIN_DEFAULT)); safef(cartVar, sizeof cartVar, "%s.%s", track->track, GTEX_EQTL_PROBABILITY); -extras->minProb = cartUsualDouble(cart, cartVar, 0.0); +extras->minProb = cartUsualDouble(cart, cartVar, GTEX_EQTL_PROBABILITY_DEFAULT); boolean hasTissueFilter = filterTissuesFromCart(track, extras); if (!hasTissueFilter && extras->minEffect == 0.0 && extras->minProb == 0.0) return; // more filtering filterItems(track, eqtlIncludeFilter, "include"); } static char *gtexEqtlClusterItemName(struct track *track, void *item) /* Left label is gene name */ { struct gtexEqtlCluster *eqtl = (struct gtexEqtlCluster *)item; return eqtl->target; } @@ -213,68 +218,72 @@ if (maxEffect < 0.0) { /* down-regulation displayed as blue */ if (maxEffect < 0.0 - cutoff) return MG_CYAN; return MG_BLUE; } /* up-regulation displayed as red */ if (maxEffect > cutoff) return MG_MAGENTA; return MG_RED; } /* Helper macros */ -#define tissueColorPatchSpacer() (tl.nWidth/4) +#define tissueColorPatchSpacer() (max(2, tl.nWidth/4)) -#define tissueColorPatchWidth() (tl.nWidth) +//#define tissueColorPatchWidth() (tl.nWidth) +//#define tissueColorPatchWidth() (tl.mWidth/2) +//#define tissueColorPatchWidth() (tl.mWidth * .75) +#define tissueColorPatchWidth() (tl.nWidth * .8) static int gtexEqtlClusterItemRightPixels(struct track *track, void *item) /* Return number of pixels we need to the right of an item (for sources label). */ { struct gtexEqtlCluster *eqtl = (struct gtexEqtlCluster *)item; int ret = mgFontStringWidth(tl.font, eqtlSourcesLabel(eqtl)); if (eqtlTissueCount(eqtl) == 1) ret += tissueColorPatchWidth() + tissueColorPatchSpacer(); return ret; } static void gtexEqtlClusterDrawItemAt(struct track *track, void *item, struct hvGfx *hvg, int xOff, int y, double scale, MgFont *font, Color color, enum trackVisibility vis) /* Draw GTEx eQTL cluster with right label indicating source(s) */ { bedDrawSimpleAt(track, item, hvg, xOff, y, scale, font, color, vis); if (vis != tvFull && vis != tvPack) return; /* Draw text to the right */ struct gtexEqtlCluster *eqtl = (struct gtexEqtlCluster *)item; +struct gtexEqtlClusterTrack *extras = (struct gtexEqtlClusterTrack *)track->extraUiData; int x2 = round((double)((int)eqtl->chromEnd-winStart)*scale) + xOff; int x = x2 + tl.mWidth/2; char *label = eqtlSourcesLabel(eqtl); int w = mgFontStringWidth(font, label); hvGfxTextCentered(hvg, x, y, w, track->heightPer, MG_BLACK, font, label); -if (eqtlTissueCount(eqtl) == 1) +if (eqtlTissueCount(eqtl) == 1 && extras->doTissueColor) { // tissue color patch (box) x += w; int h = w = tissueColorPatchWidth(); struct rgbColor tisColor = eqtlTissueColor(track, eqtl); int ix = hvGfxFindColorIx(hvg, tisColor.r, tisColor.g, tisColor.b); - hvGfxBox(hvg, x + tissueColorPatchSpacer(), y + (tl.fontHeight - h)/2 + tl.fontHeight/8, w, h, ix); + hvGfxBox(hvg, x + tissueColorPatchSpacer(), y + (tl.fontHeight - h)/2 + tl.fontHeight/10, w, h, ix); } } static void gtexEqtlClusterMapItem(struct track *track, struct hvGfx *hvg, void *item, char *itemName, char *mapItemName, int start, int end, int x, int y, int width, int height) /* Create a map box on item and label with list of tissues with colors and effect size */ { char *title = itemName; if (track->limitedVis != tvDense) { struct gtexEqtlCluster *eqtl = (struct gtexEqtlCluster *)item; // Experiment: construct list of tissues with colors and effect sizes for mouseover //struct gtexEqtlClusterTrack *extras = (struct gtexEqtlClusterTrack *)track->extraUiData; //struct hash *tissueHash = extras->tissueHash;