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/hgGtexTrackSettings/hgGtexTrackSettings.c src/hg/hgGtexTrackSettings/hgGtexTrackSettings.c index ccbe5fe..b646917 100644 --- src/hg/hgGtexTrackSettings/hgGtexTrackSettings.c +++ src/hg/hgGtexTrackSettings/hgGtexTrackSettings.c @@ -1,478 +1,480 @@ /* hgGtexTrackSettings: Configure GTEx track, with tissues selected from Body Map or list * * Copyright (C) 2016 The Regents of the University of California */ #include "common.h" #include "trackDb.h" #include "cart.h" #include "portable.h" #include "cheapcgi.h" #include "web.h" #include "hCommon.h" #include "hui.h" #include "jsHelper.h" #include "gtexUi.h" #include "gtexInfo.h" #include "gtexTissue.h" /* Global Variables */ struct cart *cart = NULL; /* CGI and other variables */ struct hash *oldVars = NULL; /* Old contents of cart before it was updated by CGI */ char *database = NULL; static void printGoButton() /* HTML for GO button and 'play' icon */ { puts( "
\n" "
GO
\n" " \n" "
\n" ); } static void printBodyMap() /* Include BodyMap SVG in HTML */ { puts( " \n" " \n" " GTEx Body Map illustration not found\n" " \n"); puts("
Credit: jwestdesign
\n"); } static void printTrackHeader(char *db, struct trackDb *tdb) /* Print top banner with track labels */ { char *assembly = stringBetween("(", ")", hFreezeFromDb(db)); puts( "\n" "
\n" "
\n" ); printf( " \n" " %s Track\n" " %s \n" " " " %s \n" , tdb->shortLabel, assembly, tdb->longLabel); puts( "\n" " \n" " \n" " \n" " \n" " \n" ); if (tdb->parent) { // link to supertrack char *encodedMapName = cgiEncode(tdb->parent->track); char *chromosome = cartUsualString(cart, "c", hDefaultChrom(database)); puts(" "); printf( " \n" " \n" " \n", hgTrackUiName(), cartSessionVarName(), cartSessionId(cart), chromosome, encodedMapName, tdb->parent->shortLabel ); freeMem(encodedMapName); } puts( "
\n" ); puts( "
\n" ); printGoButton(); puts( "
\n" "
\n" ); } static void printVisSelect(struct trackDb *tdb) /* Track visibility dropdown */ { enum trackVisibility vis = tdb->visibility; vis = hTvFromString(cartUsualString(cart, tdb->track, hStringFromTv(vis))); boolean canPack = TRUE; hTvDropDownClassVisOnlyAndExtra(tdb->track, vis, canPack, "gbSelect normalText visDD", trackDbSetting(tdb, "onlyVisibility"), NULL); } static void printScoreFilter(struct cart *cart, char *track, struct trackDb *tdb) /* Filter on overall gene expression score */ { char buf[512]; puts("Limit to genes scored at or above:\n"); safef(buf, sizeof(buf), "%s.%s", tdb->track, SCORE_FILTER); int score = cartUsualInt(cart, buf, 0); int minScore = 0, maxScore = 1000; cgiMakeIntVarWithLimits(buf, score, "Minimum score", 0, minScore, maxScore); printf( " (range %d-%d)\n", minScore, maxScore); } static void printGtexEqtlConfigPanel(struct trackDb *tdb, char *track) /* GTEx eQTL track specific controls */ { puts( " \n" "
\n" "
\n"); -gtexEqtlGene(cart, track, tdb); +gtexEqtlUiGene(cart, track, tdb); puts( "
\n" "
\n"); puts( " \n" "
\n" "
\n"); -gtexEqtlEffectSize(cart, track, tdb); +gtexEqtlUiEffectSize(cart, track, tdb); puts( "
\n" "
\n"); puts( " \n" "
\n" "
\n"); -gtexEqtlProbability(cart, track, tdb); +gtexEqtlUiProbability(cart, track, tdb); +puts("    "); +gtexEqtlUiTissueColor(cart, track, tdb); puts( "
\n" "
\n"); } static void printGtexGeneConfigPanel(struct trackDb *tdb, char *track) /* GTEx Gene track specific controls, layout in 3 rows */ { puts( " \n" "
\n" "
\n"); gtexGeneUiGeneLabel(cart, track, tdb); puts( "
\n" "
\n"); gtexGeneUiGeneModel(cart, track, tdb); puts( "
\n" "
\n"); puts( " \n" "
\n" "
\n"); gtexGeneUiLogTransform(cart, track, tdb); puts( "
\n"); puts( "
\n"); gtexGeneUiViewLimits(cart, track, tdb); puts( "
\n" "
\n"); puts( " \n" "
\n"); puts( "
\n"); gtexGeneUiCodingFilter(cart, track, tdb); puts( "
\n"); /* Filter on score */ puts( "
\n"); printScoreFilter(cart, track, tdb); puts( "
\n" "
\n"); } static void printConfigPanel(struct trackDb *tdb) /* Controls for track configuration (except for tissues) */ { puts( " \n" "
\n" "
Configuration
\n" "
\n"); /* Track vis dropdown */ printVisSelect(tdb); printGoButton(); puts( "
\n" "
\n"); /* Track-specific config */ char *track = tdb->track; if (gtexIsGeneTrack(track)) printGtexGeneConfigPanel(tdb, track); else if (gtexIsEqtlTrack(track)) printGtexEqtlConfigPanel(tdb, track); else errAbort("Unknown GTEx track: %s\n", track); puts( " \n"); } static void printTissueTable(struct trackDb *tdb) /* Output HTML with tissue labels and colors, in 2 columns, to fit next to body map */ { char *version = gtexVersion(tdb->track); struct gtexTissue *tis, *tissues = gtexGetTissues(version); char var[512]; safef(var, sizeof var, "%s.%s", tdb->track, GTEX_TISSUE_SELECT); struct hash *selectedHash = cartHashList(cart, var); struct gtexTissue **tisTable = NULL; int count = slCount(tissues); AllocArray(tisTable, count); int i=0, col=0; int cols = 2; int last = count/2 + 1; puts( " \n" "
\n" "
Tissues
\n" "
\n" " Click label below or in Body Map to set or clear a tissue\n" "
\n" "
\n" "
set all
\n" "
clear all
\n" "
\n" "
\n" ); puts( "\n"); puts( "\n"); for (tis = tissues; tis != NULL; tis = tis->next) { if (tis->id < last) i = tis->id * 2; else i = (tis->id - last) * 2 + 1; tisTable[i] = tis; } boolean all = (hashNumEntries(selectedHash) == 0) ? TRUE : FALSE; for (i=0; iname) != NULL); printf( "\n", isChecked ? tis->color : 0xFFFFFF, tis->color); printf( ""); col++; if (col > cols-1) { puts("\n"); col = 0; } } puts( "\n"); puts( "
color); printf( "style='background-color: #%06X;" "border-color: #%06X;'>%s", isChecked ? "gbmTissueSelected" : "", tis->name, tis->description); // Hidden checkbox stores value for cart printf( "", var, tis->name, isChecked ? "checked" : ""); puts( "
"); char buf[512]; safef(buf, sizeof(buf), "%s%s.%s", cgiMultListShadowPrefix(), tdb->track, GTEX_TISSUE_SELECT); cgiMakeHiddenVar(buf, "0"); } static void printTrackConfig(struct trackDb *tdb) /* Print track configuration panels, including Body Map. The layout is 2-column. Right column is body map SVG. Left column has a top panel for configuration settings (non-tissue), and a lower panel with a tissue selection list. */ { puts( "\n" "
\n" "
\n"); printConfigPanel(tdb); printTissueTable(tdb); puts( "
\n" "
\n"); printBodyMap(); puts( "
\n" "
\n" ); } static void onclickJumpToTop(char *id) /* CSP-safe click handler arrows that cause scroll to top */ { jsOnEventById("click", id, "$('html,body').scrollTop(0);"); } static void printDataInfo(char *db, struct trackDb *tdb) { puts( "\n" "
\n" "
Data Information
\n" "
\n" ); #define DATA_INFO_JUMP_ARROW_ID "hgGtexDataInfo_jumpArrow" printf( " \n", DATA_INFO_JUMP_ARROW_ID ); onclickJumpToTop(DATA_INFO_JUMP_ARROW_ID); puts( "
\n" "
\n" ); puts( "
\n" "
\n"); puts("
"); printUpdateTime(db, tdb, NULL); puts("
"); puts("
"); makeSchemaLink(db, tdb, "View table schema"); puts("
"); puts( "
\n" "
\n"); } static void printTrackDescription(struct trackDb *tdb) { puts( "\n" "
\n" "
Track Description
\n" "
\n" ); #define TRACK_INFO_JUMP_ARROW_ID "hgGtexTrackInfo_jumpArrow" printf( " \n", TRACK_INFO_JUMP_ARROW_ID ); onclickJumpToTop(TRACK_INFO_JUMP_ARROW_ID); puts( "
\n" "
\n" "
\n" "
\n"); puts(tdb->html); puts( "
\n" "
\n"); } static struct trackDb *getTrackDb(char *db, char *track) /* Check if this is an assembly with GTEx track and get trackDb */ { struct sqlConnection *conn = sqlConnect(db); if (conn == NULL) errAbort("Can't connect to database %s\n", db); char where[256]; safef(where, sizeof(where), "tableName='%s'", track); // WARNING: this will break in sandboxes unless trackDb entry is pushed to hgwdev. // The fix of using hTrackDbList() would slow for all users, so leaving as is. #define TRACKDB "trackDb" struct trackDb *tdb = trackDbLoadWhere(conn, TRACKDB, where); trackDbAddTableField(tdb); char *parent = trackDbLocalSetting(tdb, "parent"); struct trackDb *parentTdb; if (parent) { safef(where, sizeof(where), "tableName='%s'", parent); parentTdb = trackDbLoadWhere(conn, TRACKDB, where); if (parentTdb) tdb->parent = parentTdb; } sqlDisconnect(&conn); return tdb; } static void doMiddle(struct cart *theCart) /* Send HTML with javascript to display the user interface. */ { cart = theCart; char *db = NULL, *genome = NULL, *clade = NULL; getDbGenomeClade(cart, &db, &genome, &clade, oldVars); database = db; // Start web page with new-style header webStartGbNoBanner(cart, db, "Genome Browser GTEx Track Settings"); puts(""); // NOTE: This will likely go to web.c puts(""); char *track = cartUsualString(cart, "g", "gtexGene"); struct trackDb *tdb = getTrackDb(db, track); if (!tdb) errAbort("No GTEx track %s found in database %s\n", track, db); // Container for bootstrap grid layout puts( "
\n"); // Print form with configuration HTML, and track description printf( "
\n\n", hgTracksName(), cartUsualString(cart, "formMethod", "POST")); printTrackHeader(db, tdb); printTrackConfig(tdb); puts( "
"); printDataInfo(db, tdb); if (tdb->html) printTrackDescription(tdb); puts( "
"); // Initialize illustration display and handle mouseover and clicks jsIncludeFile("utils.js", NULL); jsIncludeFile("hgGtexTrackSettings.js", NULL); webIncludeFile("inc/gbFooter.html"); webEndJWest(); } int main(int argc, char *argv[]) /* Process CGI / command line. */ { /* Null terminated list of CGI Variables we don't want to save to cart */ char *excludeVars[] = {"submit", "Submit", "g", NULL}; long enteredMainTime = clock1000(); cgiSpoof(&argc, argv); oldVars = hashNew(10); cartEmptyShellNoContent(doMiddle, hUserCookie(), excludeVars, oldVars); cgiExitTime("hgGtexTrackSettings", enteredMainTime); return 0; }