638114376e8f1e12d06674874170e83d5bef0b94 markd Mon Oct 27 20:19:42 2014 -0700 Added support for gencode filter by tag and highlight by tag and annotation method. Currently only enabled in GENCODE V21. diff --git src/hg/hgTracks/gencodeTracks.c src/hg/hgTracks/gencodeTracks.c index d0f7805..8d0c9c3 100644 --- src/hg/hgTracks/gencodeTracks.c +++ src/hg/hgTracks/gencodeTracks.c @@ -11,63 +11,69 @@ #include "genePred.h" struct gencodeQuery /* structure used to store information about the query being assembled. * this allows a join to bring in additional data without having to * do repeated queries. */ { struct dyString *fields; // select fields struct dyString *from; // from clause struct dyString *where; // where clause boolean isGenePredX; // does this have the extended fields? int nextFieldCol; // next available column in result row int supportLevelCol; // support level column if joined for highlighting, or -1 int transcriptTypeCol; // transcript type column if joined for highlighting, or -1 int transcriptSourceCol; // transcript source column if joined for method highlighting, or -1 + int tagCol; // tag column if joined for method highlighting, or -1 filterBy_t *supportLevelHighlight; // choices for support level highlighting if not NULL filterBy_t *transcriptTypeHighlight; // choices for transcript type highlighting if not NULL filterBy_t *transcriptMethodHighlight; // choices for transcript method highlighting if not NULL + filterBy_t *tagHighlight; // choices for tag highlighting if not NULL boolean joinAttrs; // join the wgEncodeGencodeAttrs table - boolean joinTransSrc; // join the wgEncodeGencodeTranscriptSource table boolean joinSupportLevel; // join the wgEncodeGencodeTranscriptionSupportLevel table boolean joinTranscriptSource; // join the wgEncodeGencodeTranscriptSource table + boolean joinTag; // join the wgEncodeGencodeTag table }; static struct gencodeQuery *gencodeQueryNew(void) /* construct a new gencodeQuery object */ { struct gencodeQuery *gencodeQuery; AllocVar(gencodeQuery); gencodeQuery->fields = dyStringNew(0); gencodeQuery->from = dyStringNew(0); gencodeQuery->where = dyStringNew(0); gencodeQuery->supportLevelCol = -1; gencodeQuery->transcriptTypeCol = -1; +gencodeQuery->transcriptSourceCol = -1; +gencodeQuery->tagCol = -1; return gencodeQuery; } static void gencodeQueryFree(struct gencodeQuery **gencodeQueryPtr) /* construct a new gencodeQuery object */ { struct gencodeQuery *gencodeQuery = *gencodeQueryPtr; if (gencodeQuery != NULL) { dyStringFree(&gencodeQuery->fields); dyStringFree(&gencodeQuery->from); dyStringFree(&gencodeQuery->where); filterBySetFree(&gencodeQuery->supportLevelHighlight); filterBySetFree(&gencodeQuery->transcriptTypeHighlight); + filterBySetFree(&gencodeQuery->transcriptMethodHighlight); + filterBySetFree(&gencodeQuery->tagHighlight); freeMem(gencodeQuery); *gencodeQueryPtr = NULL; } } static void gencodeQueryBeginSubWhere(struct gencodeQuery *gencodeQuery) /* begin adding new where sub-clause */ { if (dyStringLen(gencodeQuery->where) > 0) dyStringAppend(gencodeQuery->where, " and "); dyStringAppend(gencodeQuery->where, "("); } static void gencodeQueryEndSubWhere(struct gencodeQuery *gencodeQuery) /* finish adding new where sub-clause */ @@ -129,31 +135,31 @@ { struct slName *choice = NULL; for (choice = filterBy->slChoices; choice != NULL; choice = choice->next) { if (choice != filterBy->slChoices) dyStringAppend(gencodeQuery->where, " or "); filterByMethodChoiceQuery(choice->name, gencodeQuery); } } static void filterByMethodQuery(struct track *tg, filterBy_t *filterBy, struct gencodeQuery *gencodeQuery) /* generate SQL where clause for annotation method filtering */ { gencodeQueryBeginSubWhere(gencodeQuery); filterByMethodChoicesQuery(filterBy, gencodeQuery); -gencodeQuery->joinTransSrc = TRUE; +gencodeQuery->joinTranscriptSource = TRUE; gencodeQueryEndSubWhere(gencodeQuery); } static void filterBySupportLevelChoiceQuery(char *choice, struct gencodeQuery *gencodeQuery) /* add SQL expression GENCODE support choice. */ { /* table is numeric (silly me), and string is tsl1..tsl5 or tslNA */ dyStringPrintf(gencodeQuery->where, "(supLevel.level = %s)", tslSymToNumStr(choice)); } static void filterBySupportLevelChoicesQuery(filterBy_t *filterBy, struct gencodeQuery *gencodeQuery) /* add support level compare clauses */ { struct slName *choice = NULL; for (choice = filterBy->slChoices; choice != NULL; choice = choice->next) @@ -161,53 +167,84 @@ if (choice != filterBy->slChoices) dyStringAppend(gencodeQuery->where, " or "); filterBySupportLevelChoiceQuery(choice->name, gencodeQuery); } } static void filterBySupportLevelQuery(struct track *tg, filterBy_t *filterBy, struct gencodeQuery *gencodeQuery) /* generate SQL where clause for annotation support level filtering */ { gencodeQueryBeginSubWhere(gencodeQuery); filterBySupportLevelChoicesQuery(filterBy, gencodeQuery); gencodeQuery->joinSupportLevel = TRUE; gencodeQueryEndSubWhere(gencodeQuery); } +static void filterByTagChoiceQuery(char *choice, struct gencodeQuery *gencodeQuery) +/* add SQL expression GENCODE tag choice. */ +{ +dyStringPrintf(gencodeQuery->where, "(tag.tag = \"%s\")", choice); +} + +static void filterByTagChoicesQuery(filterBy_t *filterBy, struct gencodeQuery *gencodeQuery) +/* add tag compare clauses */ +{ +struct slName *choice = NULL; +for (choice = filterBy->slChoices; choice != NULL; choice = choice->next) + { + if (choice != filterBy->slChoices) + dyStringAppend(gencodeQuery->where, " or "); + filterByTagChoiceQuery(choice->name, gencodeQuery); + } +} + +static void filterByTagQuery(struct track *tg, filterBy_t *filterBy, struct gencodeQuery *gencodeQuery) +/* generate SQL where clause for annotation tag filtering */ +{ +gencodeQueryBeginSubWhere(gencodeQuery); +filterByTagChoicesQuery(filterBy, gencodeQuery); +gencodeQuery->joinTag = TRUE; +gencodeQueryEndSubWhere(gencodeQuery); +} + static void filterByAttrsQuery(struct track *tg, filterBy_t *filterBy, struct gencodeQuery *gencodeQuery) /* handle adding on filterBy clause for attributes table */ { char *clause = filterByClause(filterBy); if (clause != NULL) { gencodeQueryBeginSubWhere(gencodeQuery); dyStringPrintf(gencodeQuery->where, "%s", clause); gencodeQuery->joinAttrs = TRUE; gencodeQueryEndSubWhere(gencodeQuery); freeMem(clause); } } static void gencodeFilterByQuery(struct track *tg, filterBy_t *filterBy, struct gencodeQuery *gencodeQuery) /* handle adding on filterBy clause for gencode */ { if (sameString(filterBy->column, "transcriptMethod")) filterByMethodQuery(tg, filterBy, gencodeQuery); else if (sameString(filterBy->column, "supportLevel")) filterBySupportLevelQuery(tg, filterBy, gencodeQuery); -else +else if (sameString(filterBy->column, "tag")) + filterByTagQuery(tg, filterBy, gencodeQuery); +else if (startsWith("attrs.", filterBy->column)) filterByAttrsQuery(tg, filterBy, gencodeQuery); +else + errAbort("gencodeFilterByQuery: don't know how to filter on column \"%s\"", filterBy->column); } static void gencodeFilterBySetQuery(struct track *tg, struct gencodeQuery *gencodeQuery) /* build where clause based on filters. */ { filterBy_t *filterBySet = filterBySetGet(tg->tdb, cart, NULL); filterBy_t *filterBy; for (filterBy = filterBySet; filterBy != NULL; filterBy = filterBy->next) { if (!filterByAllChosen(filterBy)) gencodeFilterByQuery(tg, filterBy, gencodeQuery); } filterBySetFree(&filterBySet); } @@ -221,46 +258,58 @@ } static void highlightByTranscriptTypeQuery(struct track *tg, filterBy_t *highlightBy, struct gencodeQuery *gencodeQuery) /* generate SQL where clause for obtaining transcript type for highlighting */ { dyStringAppend(gencodeQuery->fields, ", attrs.transcriptType"); gencodeQuery->transcriptTypeCol = gencodeQuery->nextFieldCol++; gencodeQuery->transcriptTypeHighlight = highlightBy; gencodeQuery->joinAttrs = TRUE; } static void highlightByTranscriptMethodQuery(struct track *tg, filterBy_t *highlightBy, struct gencodeQuery *gencodeQuery) /* generate SQL where clause for obtaining transcript type for highlighting */ { -gencodeQuery->joinTransSrc = TRUE; +gencodeQuery->joinTranscriptSource = TRUE; dyStringAppend(gencodeQuery->fields, ", transSrc.source"); gencodeQuery->transcriptSourceCol = gencodeQuery->nextFieldCol++; gencodeQuery->transcriptMethodHighlight = highlightBy; gencodeQuery->joinAttrs = TRUE; } +static void highlightByTagQuery(struct track *tg, filterBy_t *highlightBy, struct gencodeQuery *gencodeQuery) +/* generate SQL where clause for obtaining tag for highlighting */ +{ +gencodeQuery->joinTag = TRUE; +dyStringAppend(gencodeQuery->fields, ", tag.tag"); +gencodeQuery->tagCol = gencodeQuery->nextFieldCol++; +gencodeQuery->tagHighlight = highlightBy; +gencodeQuery->joinTag = TRUE; +} + static void gencodeHighlightByQuery(struct track *tg, filterBy_t *highlightBy, struct gencodeQuery *gencodeQuery) /* Handle a highlight by category. highlightBy object will be saved in gencodeQuery */ { if (sameString(highlightBy->column, "supportLevel")) highlightBySupportLevelQuery(tg, highlightBy, gencodeQuery); else if (sameString(highlightBy->column, "attrs.transcriptType")) highlightByTranscriptTypeQuery(tg, highlightBy, gencodeQuery); else if (sameString(highlightBy->column, "transcriptMethod")) highlightByTranscriptMethodQuery(tg, highlightBy, gencodeQuery); +else if (sameString(highlightBy->column, "tag")) + highlightByTagQuery(tg, highlightBy, gencodeQuery); else errAbort("BUG: gencodeHighlightByQuery unknown highlight column: \"%s\"", highlightBy->column); } static void gencodeHighlightBySetQuery(struct track *tg, struct gencodeQuery *gencodeQuery) /* build add join and fields to include to provide data for highlighting. This results * in extra columns being returned. */ { filterBy_t *highlightBySet = highlightBySetGet(tg->tdb, cart, NULL); filterBy_t *highlightBy; while ((highlightBy = slPopHead(&highlightBySet)) != NULL) { if (!filterByAllChosen(highlightBy)) gencodeHighlightByQuery(tg, highlightBy, gencodeQuery); else @@ -322,72 +371,88 @@ static bool highlightByTranscriptMethodSelected(char **row, struct gencodeQuery *gencodeQuery) /* is the transcript type associated with this transcript selected? */ { if (gencodeQuery->transcriptMethodHighlight != NULL) { struct slName *choice; for (choice = gencodeQuery->transcriptMethodHighlight->slChoices; choice != NULL; choice = choice->next) { if (highlightByTranscriptMethodMatch(choice->name, row[gencodeQuery->transcriptSourceCol])) return TRUE; } } return FALSE; } +static bool highlightByTagSelected(char **row, struct gencodeQuery *gencodeQuery) +/* is the tag associated with this transcript selected? */ +{ +if (gencodeQuery->tagHighlight == NULL) + return FALSE; // no highlighting by tag +else + return slNameInList(gencodeQuery->tagHighlight->slChoices, row[gencodeQuery->tagCol]); +} + static unsigned getHighlightColor(struct track *tg) /* get the highlightColor from trackDb, or a default if not found */ { unsigned char red = 255, green = 165, blue = 0; // Orange default char *colorStr = trackDbSetting(tg->tdb, "highlightColor"); if (colorStr != NULL) parseColor(colorStr, &red, &green, &blue); return MAKECOLOR_32(red, green, blue); } static void highlightByGetColor(char **row, struct gencodeQuery *gencodeQuery, unsigned highlightColor, struct linkedFeatures *lf) /* compute the highlight color based on a extra fields returned in a row, setting * the linkedFeatures field */ { -if (highlightBySupportLevelSelected(row, gencodeQuery) || highlightByTranscriptTypeSelected(row, gencodeQuery) - || highlightByTranscriptMethodSelected(row, gencodeQuery)) +if (highlightBySupportLevelSelected(row, gencodeQuery) + || highlightByTranscriptTypeSelected(row, gencodeQuery) + || highlightByTranscriptMethodSelected(row, gencodeQuery) + || highlightByTagSelected(row, gencodeQuery)) { lf->highlightColor = highlightColor; lf->highlightMode = highlightBackground; } } static void addQueryTables(struct track *tg, struct gencodeQuery *gencodeQuery) /* add required from tables and joins */ { sqlDyStringPrintfFrag(gencodeQuery->from, "%s g", tg->table); if (gencodeQuery->joinAttrs) { sqlDyStringPrintf(gencodeQuery->from, ", %s attrs", trackDbRequiredSetting(tg->tdb, "wgEncodeGencodeAttrs")); dyStringAppend(gencodeQuery->where, " and (attrs.transcriptId = g.name)"); } -if (gencodeQuery->joinTransSrc) +if (gencodeQuery->joinTranscriptSource) { sqlDyStringPrintf(gencodeQuery->from, ", %s transSrc", trackDbRequiredSetting(tg->tdb, "wgEncodeGencodeTranscriptSource")); dyStringAppend(gencodeQuery->where, " and (transSrc.transcriptId = g.name)"); } if (gencodeQuery->joinSupportLevel) { sqlDyStringPrintf(gencodeQuery->from, ", %s supLevel", trackDbRequiredSetting(tg->tdb, "wgEncodeGencodeTranscriptionSupportLevel")); dyStringAppend(gencodeQuery->where, " and (supLevel.transcriptId = g.name)"); } +if (gencodeQuery->joinTag) + { + sqlDyStringPrintf(gencodeQuery->from, ", %s tag", trackDbRequiredSetting(tg->tdb, "wgEncodeGencodeTag")); + dyStringAppend(gencodeQuery->where, " and (tag.transcriptId = g.name)"); + } } static boolean tableIsGenePredX(struct track *tg) /* determine if a table has genePred extended fields. two-way consensus * pseudo doesn't have them. */ { struct sqlConnection *conn = hAllocConn(database); struct slName *fields = sqlFieldNames(conn, tg->table); hFreeConn(&conn); boolean isGenePredX = slNameInList(fields, "score"); slFreeList(&fields); return isGenePredX; } static struct gencodeQuery *gencodeQueryConstruct(struct track *tg)