5a63b70b7e8405a187c8fba71c557cca655e0424 kate Wed Aug 24 12:17:38 2016 -0700 Add config option to display ENS geneId. For synergy with new GTEx gene sorter column. refs #17288 diff --git src/hg/hgTracks/gtexTracks.c src/hg/hgTracks/gtexTracks.c index 1bd5a34..5a9b71b 100644 --- src/hg/hgTracks/gtexTracks.c +++ src/hg/hgTracks/gtexTracks.c @@ -2,55 +2,76 @@ /* Copyright (C) 2015 The Regents of the University of California * See README in this or parent directory for licensing information. */ #include "common.h" #include "hgTracks.h" #include "hvGfx.h" #include "rainbow.h" #include "gtexInfo.h" #include "gtexGeneBed.h" #include "gtexTissue.h" #include "gtexTissueData.h" #include "gtexUi.h" #include "spaceSaver.h" +enum geneLabelStyle + { + LABEL_GENE_SYMBOL = 0, + LABEL_GENE_ACCESSION = 1, + LABEL_BOTH = 2 + }; + +static enum geneLabelStyle getLabelStyle(char *cartVar) +/* Get enum corresponding to cart var */ +{ + if (sameString(GTEX_LABEL_SYMBOL, cartVar)) + return LABEL_GENE_SYMBOL; + if (sameString(GTEX_LABEL_ACCESSION, cartVar)) + return LABEL_GENE_ACCESSION; + if (sameString(GTEX_LABEL_BOTH, cartVar)) + return LABEL_BOTH; + return LABEL_GENE_SYMBOL; +} + struct gtexGeneExtras /* Track info */ { char *version; /* Suffix to table name, e.g. 'V6' */ boolean codingOnly; /* User filter to limit display to coding genes */ boolean showExons; /* Show gene model exons */ boolean noWhiteout; /* Suppress whiteout of graph background (allow highlight, blue lines) */ + enum geneLabelStyle labelStyle; /* Show gene symbol, accession, or both */ double maxMedian; /* Maximum median rpkm for all tissues */ boolean isComparison; /* Comparison of two sample sets (e.g. male/female). */ boolean isDifference; /* True if comparison is shown as a single difference graph. False if displayed as two graphs, one oriented downward */ char *graphType; /* Additional info about graph (e.g. type of comparison graph */ struct rgbColor *colors; /* Color palette for tissues */ boolean doLogTransform; /* Log10(x+1) */ struct gtexTissue *tissues; /* Cache tissue names, descriptions */ struct hash *tissueFilter; /* For filter. NULL out excluded tissues */ }; struct gtexGeneInfo /* GTEx gene model, names, and expression medians */ { struct gtexGeneInfo *next; /* Next in singly linked list */ struct gtexGeneBed *geneBed;/* Gene name, id, type, exp count and medians from BED table */ struct genePred *geneModel; /* Gene structure from model table */ + char *label; /* Name, accession, or both */ char *description; /* Gene description */ double *medians1; /* Computed medians */ double *medians2; /* Computed medians for comparison (inverse) graph */ int height; /* Item height in pixels */ }; #define MAX_DESC 200 /***********************************************/ /* Color gene models using GENCODE conventions */ static struct rgbColor codingColor = {12, 12, 120}; // #0C0C78 static struct rgbColor nonCodingColor = {0, 100, 0}; // #006400 static struct rgbColor pseudoColor = {255,51,255}; // #FF33FF static struct rgbColor problemColor = {254, 0, 0}; // #FE0000 @@ -388,30 +409,32 @@ char *samples = cartUsualStringClosestToHome(cart, tg->tdb, FALSE, GTEX_SAMPLES, GTEX_SAMPLES_DEFAULT); extras->graphType = cloneString(samples); if (sameString(samples, GTEX_SAMPLES_COMPARE_SEX)) extras->isComparison = TRUE; char *comparison = cartUsualStringClosestToHome(cart, tg->tdb, FALSE, GTEX_COMPARISON_DISPLAY, GTEX_COMPARISON_DEFAULT); extras->isDifference = sameString(comparison, GTEX_COMPARISON_DIFF) ? TRUE : FALSE; extras->maxMedian = gtexMaxMedianScore(extras->version); extras->codingOnly = cartUsualBooleanClosestToHome(cart, tg->tdb, FALSE, GTEX_CODING_GENE_FILTER, GTEX_CODING_GENE_FILTER_DEFAULT); extras->showExons = cartUsualBooleanClosestToHome(cart, tg->tdb, FALSE, GTEX_SHOW_EXONS, GTEX_SHOW_EXONS_DEFAULT); extras->noWhiteout = cartUsualBooleanClosestToHome(cart, tg->tdb, FALSE, GTEX_NO_WHITEOUT, GTEX_NO_WHITEOUT_DEFAULT); +extras->labelStyle = getLabelStyle(cartUsualStringClosestToHome(cart, tg->tdb, FALSE, GTEX_LABEL, + GTEX_LABEL_DEFAULT)); /* Get geneModels in range */ char buf[256]; char *modelTable = "gtexGeneModel"; safef(buf, sizeof(buf), "%s%s", modelTable, extras->version ? extras->version: ""); struct hash *modelHash = loadGeneModels(buf); /* Get geneBeds (names and all-sample tissue median scores) in range */ char *filter = getScoreFilterClause(cart, tg->tdb, NULL); bedLoadItemWhere(tg, tg->table, filter, (ItemLoader)gtexGeneBedLoad); /* Create geneInfo items with BED and geneModels */ struct gtexGeneInfo *geneInfo = NULL, *list = NULL; struct gtexGeneBed *geneBed = (struct gtexGeneBed *)tg->items; /* Load tissue colors: GTEx or rainbow */ @@ -433,61 +456,80 @@ extras->colors = getRainbow(&saturatedRainbowAtPos, expCount); } } filterTissues(tg); while (geneBed != NULL) { if (extras->codingOnly && !gtexGeneIsCoding(geneBed)) { // apologies for messy short-circuit geneBed = geneBed->next; continue; } AllocVar(geneInfo); geneInfo->geneBed = geneBed; + + // set label + if (extras->labelStyle == LABEL_GENE_SYMBOL) + geneInfo->label = geneBed->name; + else if (extras->labelStyle == LABEL_GENE_ACCESSION) + geneInfo->label = geneBed->geneId; + else if (extras->labelStyle == LABEL_BOTH) + { + char buf[256]; + safef(buf, sizeof(buf), "%s/%s", geneBed->name, geneBed->geneId); + geneInfo->label = cloneString(buf); + } + else + geneInfo->label = ""; + + // get description geneInfo->geneModel = hashFindVal(modelHash, geneBed->geneId); // sometimes this is missing, hash returns NULL. do we check? // NOTE: Consider loading all gene descriptions to save queries char query[256]; sqlSafef(query, sizeof(query), "select kgXref.description from kgXref where geneSymbol='%s'", geneBed->name); struct sqlConnection *conn = hAllocConn(database); char *desc = sqlQuickString(conn, query); hFreeConn(&conn); if (desc) { // hg38 known genes has extra detail about source; strip it char *fromDetail = strstrNoCase(desc, "(from"); if (fromDetail) *fromDetail = 0; if (strlen(desc) > MAX_DESC) strcpy(desc+MAX_DESC, "..."); // also strip 'homo sapiens' prefix #define SPECIES_PREFIX "Homo sapiens " if (startsWith(SPECIES_PREFIX, desc)) desc += strlen(SPECIES_PREFIX); geneInfo->description = desc; } else geneInfo->description = geneInfo->geneBed->name; + slAddHead(&list, geneInfo); geneBed = geneBed->next; geneInfo->geneBed->next = NULL; + if (extras->isComparison && (tg->visibility == tvFull || tg->visibility == tvPack)) // compute medians based on configuration (comparisons, and later, filters) loadComputedMedians(geneInfo, extras); geneInfo->height = gtexGeneItemHeight(tg, geneInfo); + } slReverse(&list); tg->items = list; } /***********************************************/ /* Draw */ /* Bargraph layouts for three window sizes */ #define WIN_MAX_GRAPH 50000 #define MAX_GRAPH_HEIGHT 175 #define MAX_BAR_WIDTH 5 #define MAX_GRAPH_PADDING 2 #define WIN_MED_GRAPH 500000 @@ -1022,32 +1064,31 @@ // map over label int itemHeight = geneInfo->height; mapBoxHc(hvg, geneStart, geneEnd, x1-labelWidth, y, labelWidth, itemHeight-3, tg->track, mapItemName, geneInfo->description); // map over gene model (extending to end of item) int geneModelHeight = gtexGeneModelHeight(extras); mapBoxHc(hvg, geneStart, geneEnd, x1, y+itemHeight-geneModelHeight-3, w, geneModelHeight, tg->track, mapItemName, geneInfo->description); } } static char *gtexGeneItemName(struct track *tg, void *item) /* Return gene name */ { struct gtexGeneInfo *geneInfo = (struct gtexGeneInfo *)item; -struct gtexGeneBed *geneBed = geneInfo->geneBed; -return geneBed->name; +return geneInfo->label; } static int gtexGeneHeight(void *item) { struct gtexGeneInfo *geneInfo = (struct gtexGeneInfo *)item; assert(geneInfo->height != 0); return geneInfo->height; } static int gtexGeneTotalHeight(struct track *tg, enum trackVisibility vis) /* Figure out total height of track. Set in track and also return it */ { int height = 0; int lineHeight = 0; int heightPer = 0;