1f1b38c1c05c0e0011260a38a9eb926cd6038afd max Tue Mar 12 14:00:43 2013 -0700 new pubsBlat format allows to specify mouseover text and labels as part of primary table, without join. Also allows to define classes of papers and color them via a second table diff --git src/hg/hgTracks/simpleTracks.c src/hg/hgTracks/simpleTracks.c index 13b5b4a..252695d 100644 --- src/hg/hgTracks/simpleTracks.c +++ src/hg/hgTracks/simpleTracks.c @@ -1,28 +1,29 @@ /* infrastructure -- Code shared by all tracks. Separating this out from * hgTracks.c allows a standalone main to make track images. */ /* NOTE: This code was imported from hgTracks.c 1.1469, May 19 2008, * so a lot of revision history has been obscured. To see code history * from before this file was created, run this: * cvs ann -r 1.1469 hgTracks.c | less +Gp */ #include "common.h" #include "spaceSaver.h" #include "portable.h" #include "bed.h" +#include "basicBed.h" #include "psl.h" #include "web.h" #include "hdb.h" #include "hgFind.h" #include "hCommon.h" #include "hgColors.h" #include "trackDb.h" #include "bedCart.h" #include "wiggle.h" #include "lfs.h" #include "grp.h" #include "chromColors.h" #include "hgTracks.h" #include "subText.h" #include "cds.h" @@ -12076,95 +12077,191 @@ ; while(*str) { matchStr[i++] = '+'; for(; *str && !isspace(*str);str++) matchStr[i++] = *str; for(;*str && isspace(*str);str++) ; } matchStr[i++] = 0; return matchStr; } struct pubsExtra /* additional info needed for publication blat linked features: author+year and title */ { - char* label; - char* mouseOver; + char *label; // usually author+year + char *mouseOver; // usually title of article + // color depends on cart settings, either based on topic, impact or year + // support to ways to color: either by shade (year, impact) or directly with rgb values + int shade; // year or impact are shades which we can't resolve to rgb easily + struct rgbColor *color; }; +/* assignment of pubs classes to colors */ +static struct hash* pubsClassColors = NULL; + +static void pubsParseClassColors() +/* parse class colors from hgFixed.pubsClassColors into the hash pubsClassColors */ +{ +if (pubsClassColors!=NULL) + return; + +pubsClassColors = hashNew(0); +struct sqlConnection *conn = hAllocConn(database); +if (!sqlTableExists(conn, "hgFixed.pubsClassColors")) + { + //fprintf(stderr, "simpleTracks.c: table hgFixed.pubsClassColors does not exist\n"); + return; + } +char *query = "SELECT class, rgbColor FROM hgFixed.pubsClassColors"; +struct sqlResult *sr = sqlGetResult(conn, query); +char **row = NULL; +if ((row = sqlNextRow(sr)) != NULL) + { + char *class = row[0]; + char *colStr = row[1]; + // copied from genePredItemClassColor - is there no function for this? + char *rgbVals[5]; + chopString(colStr, ",", rgbVals, sizeof(rgbVals)); + struct rgbColor *rgb; + AllocVar(rgb); + rgb->r = (sqlUnsigned(rgbVals[0])); + rgb->g = (sqlUnsigned(rgbVals[1])); + rgb->b = (sqlUnsigned(rgbVals[2])); + //printf("Adding hash: %s -> %d,%d,%d", class, rgb->r, rgb->g, rgb->b); + hashAdd(pubsClassColors, cloneString(class), rgb); + } +sqlFreeResult(&sr); +} + static char* pubsFeatureLabel(char* author, char* year) /* create label <author><year> given authors and year strings */ { char* authorYear = NULL; if (isEmpty(author)) author = "NoAuthor"; if (isEmpty(year)) year = "NoYear"; authorYear = catTwoStrings(author, year); return authorYear; } -static struct pubsExtra *pubsMakeExtra(char* articleTable, struct sqlConnection* conn, - struct linkedFeatures* lf) +static struct pubsExtra *pubsMakeExtra(struct track* tg, char* articleTable, + struct sqlConnection* conn, struct linkedFeatures* lf) +/* bad solution: a function that is called before the extra field is + * accessed and that fills it from a sql query. Will need to redo this like gencode, + * drawing from atom, variome and bedLoadN or bedDetails */ { char query[LARGEBUF]; struct sqlResult *sr = NULL; char **row = NULL; struct pubsExtra *extra = NULL; +/* support two different storage places for article data: either the bed table directly + * includes the title + author of the article or we have to look it up from the articles + * table. Having a copy of the title in the bed table is faster */ +bool newFormat = false; +if (sqlColumnExists(conn, tg->table, "title")) + { + safef(query, sizeof(query), "SELECT firstAuthor, year, title, impact, classes FROM %s " + "WHERE chrom = '%s' and chromStart = '%d' and name='%s'", tg->table, chromName, lf->start, lf->name); + newFormat = true; + } +else + { safef(query, sizeof(query), "SELECT firstAuthor, year, title FROM %s WHERE articleId = '%s'", articleTable, lf->name); + newFormat = false; + } + sr = sqlGetResult(conn, query); if ((row = sqlNextRow(sr)) != NULL) { char* firstAuthor = row[0]; char* year = row[1]; char* title = row[2]; + char* impact = NULL; + char* classes = NULL; extra = needMem(sizeof(struct pubsExtra)); extra->label = pubsFeatureLabel(firstAuthor, year); if (isEmpty(title)) extra->mouseOver = extra->label; else extra->mouseOver = cloneString(title); + extra->color = NULL; + extra->shade = -1; + + if (newFormat) + { + impact = row[3]; + classes = row[4]; + if (!isEmpty(impact)) + { + char *colorBy = cartOptionalStringClosestToHome(cart, tg->tdb, FALSE, "pubsColorBy"); + if (strcmp(colorBy,"impact")==0) + { + char impInt = atoi(impact); + extra->shade = impInt/25; + } + if (strcmp(colorBy,"year")==0) + { + int relYear = (atoi(year)-1990); + extra->shade = min(relYear/3, 10); + //extra->color = shadesOfGray[yearShade]; + } + if (strcmp(colorBy,"topic")==0) + { + char *class; + while ((class=cloneNextWordByDelimiter(&classes, ','))!=NULL) + { + struct rgbColor *col = (struct rgbColor*) hashFindVal(pubsClassColors, class); + extra->color = col; + } + } + + } + } } + sqlFreeResult(&sr); return extra; } static void pubsAddExtra(struct track* tg, struct linkedFeatures* lf) /* add authorYear and title to linkedFeatures->extra */ { char *articleTable = trackDbSettingClosestToHome(tg->tdb, "pubsArticleTable"); if(isEmpty(articleTable)) return; if (lf->extra != NULL) return; struct sqlConnection *conn = hAllocConn(database); -struct pubsExtra* extra = pubsMakeExtra(articleTable, conn, lf); +struct pubsExtra* extra = pubsMakeExtra(tg, articleTable, conn, lf); lf->extra = extra; hFreeConn(&conn); } static void pubsLoadKeywordYearItems(struct track *tg) /* load items that fulfill keyword and year filter */ { +pubsParseClassColors(); struct sqlConnection *conn = hAllocConn(database); char *keywords = cartOptionalStringClosestToHome(cart, tg->tdb, FALSE, "pubsKeywords"); char *yearFilter = cartOptionalStringClosestToHome(cart, tg->tdb, FALSE, "pubsYear"); char *articleTable = pubsArticleTable(tg); if(yearFilter == NULL || sameWord(yearFilter, "anytime")) yearFilter = NULL; if(isNotEmpty(keywords)) keywords = makeMysqlMatchStr(sqlEscapeString(keywords)); if(isEmpty(yearFilter) && isEmpty(keywords)) { loadGappedBed(tg); } @@ -12222,30 +12319,50 @@ * into the cart and activate the track. */ { char *articleId = cgiOptionalString(PUBSFILTERNAME); //if (articleId==NULL) //articleId = cartOptionalString(cart, PUBSFILTERNAME); if (articleId!=NULL) { cartSetString(cart, PUBSFILTERNAME, articleId); tdbSetCartVisibility(tg->tdb, cart, hCarefulTrackOpenVis(database, tg->track)); tg->visibility=tvPack; } } +Color pubsItemColor(struct track *tg, void *item, struct hvGfx *hvg) +/* get color from extra field */ +{ +//pubsParseClassColors(); +struct linkedFeatures *lf = item; +pubsAddExtra(tg, lf); + +struct pubsExtra* extra = lf->extra; +if (extra==NULL || (extra->color==NULL && extra->shade==-1)) + return MG_BLACK; + +if (extra->shade != -1) + return shadesOfBlue[extra->shade]; +else + { + //printf("got item color %d", extra->color->r); + return hvGfxFindRgb(hvg, extra->color); + } +} + char *pubsItemName(struct track *tg, void *item) /* get author/year from extra field */ { struct linkedFeatures *lf = item; pubsAddExtra(tg, lf); struct pubsExtra* extra = lf->extra; if (extra!=NULL) return extra->label; else return lf->name; } static void pubsMapItem(struct track *tg, struct hvGfx *hvg, void *item, @@ -12376,30 +12493,31 @@ static void pubsBlatPslMethods(struct track *tg) /* a track that shows only the indiv matches for one single article */ { activatePslTrackIfCgi(tg); tg->loadItems = pubsPslLoadItems; tg->itemName = pubsItemName; tg->mapItem = pubsMapItem; } static void pubsBlatMethods(struct track *tg) /* publication blat tracks are bed12+2 tracks of sequences in text, mapped with BLAT */ { //bedMethods(tg); tg->loadItems = pubsLoadKeywordYearItems; tg->itemName = pubsItemName; +tg->itemColor = pubsItemColor; tg->mapItem = pubsMapItem; } static void pubsMarkerMethods(struct track *tg) /* publication marker tracks are bed5 tracks of genome marker occurences like rsXXXX found in text*/ { tg->mapItem = pubsMarkerMapItem; tg->itemName = pubsMarkerItemName; } void fillInFromType(struct track *track, struct trackDb *tdb) /* Fill in various function pointers in track from type field of tdb. */ { char *typeLine = tdb->type, *words[8], *type; int wordCount;