51669978674f8d49a13b96e72d71418633719176 max Tue Mar 20 02:35:48 2012 -0700 creating a authorYear label on the fly for pubBlat tracks diff --git src/hg/hgTracks/simpleTracks.c src/hg/hgTracks/simpleTracks.c index 1615972..f714f64 100644 --- src/hg/hgTracks/simpleTracks.c +++ src/hg/hgTracks/simpleTracks.c @@ -12134,202 +12134,280 @@ track->visibility = tvDense; track->limitedVis = tvDense; track->limitedVisSet = TRUE; } track->nextItemButtonable = track->nextExonButtonable = FALSE; track->nextPrevItem = NULL; track->nextPrevExon = NULL; } char* pubsArticleTable(struct track *tg) /* return the name of the pubs articleTable, either * the value from the trackDb statement 'articleTable' * or the default value: <trackName>Article */ { char *articleTable = trackDbSetting(tg->tdb, "pubsArticleTable"); -if (articleTable == NULL) +if (isEmpty(articleTable)) { char buf[256]; safef(buf, sizeof(buf), "%sArticle", tg->track); articleTable = cloneString(buf); } return articleTable; } static char *makeMysqlMatchStr(char *str) { // return a string with all words prefixed with a '+' to force a boolean AND query; // we also strip leading/trailing spaces. char *matchStr = needMem(strlen(str) * 2 + 1); int i = 0; for(;*str && isspace(*str);str++) - ; -while(*str) + ; while(*str) { matchStr[i++] = '+'; for(; *str && !isspace(*str);str++) matchStr[i++] = *str; for(;*str && isspace(*str);str++) ; } matchStr[i++] = 0; return matchStr; } -static void pubsLoadItems(struct track *tg) -/* apply filter to pubs items */ +struct pubsExtra +/* additional info needed for publication blat linked features: author+year and title */ +{ + char* authorYear; + char* title; +}; + +static char* pubsGetFirstAuthor(char* authors) +/* return first author from author field */ +{ +char* author = firstWordInLine(authors); +stripChar(author, ','); +stripChar(author, ';'); + +if (isEmpty(author)) + author = "NoAuthor"; +return author; +} + +static struct pubsExtra *pubsMakeExtra(char* articleTable, struct sqlConnection* conn, + struct linkedFeatures* lf) +{ +char query[LARGEBUF]; +safef(query, sizeof(query), "SELECT authors, year, title FROM %s WHERE articleId = '%s'", + articleTable, lf->name); +struct sqlResult *sr = NULL; +char **row = NULL; +sr = sqlGetResult(conn, query); +struct pubsExtra *extra = NULL; +if ((row = sqlNextRow(sr)) != NULL) +{ + char* author = pubsGetFirstAuthor(row[0]); + char* year = row[1]; + char* title = row[2]; + if (isEmpty(year)) + year = "NoYear"; + + extra = needMem(sizeof(struct pubsExtra)); + extra->authorYear = catTwoStrings(author, year); + if (isEmpty(title)) + extra->title = extra->authorYear; + else + extra->title = cloneString(title); +} + +sqlFreeResult(&sr); +return extra; +} + +static void pubsLookupAuthors(struct track *tg) +/* add authorYear and title to all linkedFeatures->extra */ +{ +enum trackVisibility vis = tg->visibility; +if (vis == tvDense || vis == tvSquish) + return; + +char *articleTable = pubsArticleTable(tg); +if(isEmpty(articleTable)) + return; + +struct linkedFeatures *lf = NULL; + +struct sqlConnection *conn = hAllocConn(database); +for (lf = tg->items; lf != NULL; lf = lf->next) +{ + struct pubsExtra* extra = pubsMakeExtra(articleTable, conn, lf); + lf->extra = extra; +} +hFreeConn(&conn); +} + +static void pubsLoadKeywordYearItems(struct track *tg) +/* load items that fulfill keyword and year filter */ { struct sqlConnection *conn = hAllocConn(database); char *keywords = cartOptionalString(cart, "pubsKeywords"); char *yearFilter = cartOptionalString(cart, "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); else { char extra[2048], yearWhere[256], keywordsWhere[1024], prefix[256]; char **row; int rowOffset; struct linkedFeatures *lfList = NULL; struct trackDb *tdb = tg->tdb; int scoreMin = atoi(trackDbSettingClosestToHomeOrDefault(tdb, "scoreMin", "0")); int scoreMax = atoi(trackDbSettingClosestToHomeOrDefault(tdb, "scoreMax", "1000")); boolean useItemRgb = bedItemRgb(tdb); - safef(prefix, sizeof(prefix), "name IN (SELECT displayId FROM %s WHERE", articleTable); + safef(prefix, sizeof(prefix), "name IN (SELECT articleId FROM %s WHERE", articleTable); if(isNotEmpty(keywords)) safef(keywordsWhere, sizeof(keywordsWhere), "MATCH (citation, title, authors, abstract) AGAINST ('%s' IN BOOLEAN MODE)", keywords); if(isNotEmpty(yearFilter)) safef(yearWhere, sizeof(yearWhere), "year >= '%s'", sqlEscapeString(yearFilter)); + if(isEmpty(keywords)) safef(extra, sizeof(extra), "%s %s)", prefix, yearWhere); else if(isEmpty(yearFilter)) safef(extra, sizeof(extra), "%s %s)", prefix, keywordsWhere); else safef(extra, sizeof(extra), "%s %s AND %s)", prefix, yearWhere, keywordsWhere); struct sqlResult *sr = hExtendedRangeQuery(conn, tg->table, chromName, winStart, winEnd, extra, FALSE, NULL, &rowOffset); while ((row = sqlNextRow(sr)) != NULL) { struct bed *bed = bedLoad12(row+rowOffset); slAddHead(&lfList, bedMungToLinkedFeatures(&bed, tdb, 12, scoreMin, scoreMax, useItemRgb)); } sqlFreeResult(&sr); slReverse(&lfList); slSort(&lfList, linkedFeaturesCmp); tg->items = lfList; } hFreeConn(&conn); } +static void pubsLoadItems(struct track *tg) +/* filter items and stuff item data from other tables (author name, title) into extra field */ +{ +pubsLoadKeywordYearItems(tg); +pubsLookupAuthors(tg); +} + +char *pubsItemName(struct track *tg, void *item) +/* get author/year from extra field */ +{ +struct linkedFeatures *lf = item; +struct pubsExtra* extra = lf->extra; +if (extra!=NULL) + return extra->authorYear; +else + return lf->name; +} + static void pubsMapItem(struct track *tg, struct hvGfx *hvg, void *item, char *itemName, char *mapItemName, int start, int end, int x, int y, int width, int height) -/* create mouse overs with titles for pubs bed features */ +/* create mouse over with title for pubs blat features. */ { if(!theImgBox || tg->limitedVis != tvDense || !tdbIsCompositeChild(tg->tdb)) { - char query[1024], title[4096]; - char *label = NULL; - char *articleTable = pubsArticleTable(tg); - if(!isEmpty(articleTable)) + struct linkedFeatures *lf = item; + char* mouseOver = NULL; + if (lf->extra != NULL) { - struct sqlConnection *conn = hAllocConn(database); - safef(query, sizeof(query), "select title from %s where displayId = '%s'", articleTable, mapItemName); - label = sqlQuickQuery(conn, query, title, sizeof(title)); - hFreeConn(&conn); + struct pubsExtra *extra = lf->extra; + mouseOver = extra->title; } - if(isEmpty(label)) - label = mapItemName; - mapBoxHc(hvg, start, end, x, y, width, height, tg->track, mapItemName, label); + else + mouseOver = itemName; + + mapBoxHc(hvg, start, end, x, y, width, height, tg->track, mapItemName, mouseOver); } } -char* pubsLastMarkerName; - char *pubsMarkerItemName(struct track *tg, void *item) -/* retrieve article count from extra field, and return - * side effect: save original name in global var for mapItem - * Is this too hacky? No idea where I could save the original name otherwise... */ +/* retrieve article count from score field and return.*/ { struct bed *bed = item; -char query[256]; -char *escName = sqlEscapeString(bed->name); -safef(query, sizeof(query), "select matchCount from %s where name = '%s'", tg->table, escName); - -char *articleCount = NULL; -struct sqlConnection *conn = hAllocConn(database); -articleCount = sqlQuickString(conn, query); -char* newName = catTwoStrings(articleCount, " articles"); -freeMem(articleCount); -hFreeConn(&conn); -pubsLastMarkerName = bed->name; -return newName; +char newName[64]; +safef(newName, sizeof(newName), "%d articles", (int) bed->score); +return cloneString(newName); } static void pubsMarkerMapItem(struct track *tg, struct hvGfx *hvg, void *item, char *itemName, char *mapItemName, int start, int end, int x, int y, int width, int height) /* use previously saved itemName for the mouseOver */ { genericMapItem(tg, hvg, item, - pubsLastMarkerName, mapItemName, start, end, + itemName, mapItemName, start, end, x, y, width, height); } -static void pubsMethods(struct track *tg) -{ -if (startsWith("pubsMarker", tg->table)) -{ - tg->mapItem = pubsMarkerMapItem; - tg->itemName = pubsMarkerItemName; -} -else +static void pubsBlatMethods(struct track *tg) +/* publication blat tracks are bed12+2 tracks of sequences in text, mapped with BLAT */ { tg->loadItems = pubsLoadItems; + tg->itemName = pubsItemName; 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; if (typeLine == NULL) return; wordCount = chopLine(cloneString(typeLine), words); if (wordCount <= 0) return; type = words[0]; #ifndef GBROWSE if (sameWord(type, "bed")) { complexBedMethods(track, tdb, FALSE, wordCount, words); /* bed.h includes genePred.h so should be able to use these trackDb settings. */ if (trackDbSetting(track->tdb, GENEPRED_CLASS_TBL) !=NULL) track->itemColor = genePredItemClassColor; - if (startsWith("pubs", track->table) ) - pubsMethods(track); + if (hashFindVal(tdb->settingsHash, "pubsMarkerTable")) + pubsMarkerMethods(track); + if (hashFindVal(tdb->settingsHash, "pubsSequenceTable")) + pubsBlatMethods(track); } /* else if (sameWord(type, "bedLogR")) { wordCount++; words[1] = "9"; complexBedMethods(track, tdb, FALSE, wordCount, words); //track->bedSize = 10; } */ else if (sameWord(type, "bigBed")) { bigBedMethods(track, tdb, wordCount, words); if (trackShouldUseAjaxRetrieval(track)) track->loadItems = dontLoadItems;