429264c3158dd36342484a11b0289f929261e2eb ceisenhart Wed Nov 5 14:50:34 2014 -0800 Added a feature to bold canonical gene names on intermediate page when the user searches an ambiguous gene name (IE foxp2). diff --git src/hg/lib/hgFind.c src/hg/lib/hgFind.c index 4dd7d86..eb415c1 100644 --- src/hg/lib/hgFind.c +++ src/hg/lib/hgFind.c @@ -576,46 +576,66 @@ } freez(&indexPath); return result; } struct tsrPos /* Little helper structure tying together search result * and pos, used by addKnownGeneItems */ { struct tsrPos *next; /* Next in list. */ struct trixSearchResult *tsr; /* Basically a gene symbol */ struct hgPos *posList; /* Associated list of positions. */ }; +static boolean isCanonical(struct sqlConnection *conn, char *geneName) +/* Look for the name in knownCannonical, return true if found */ +{ +boolean foundIt = FALSE; +if (sqlTableExists(conn, "knownCanonical")) + { + char query[512]; + sqlSafef(query, sizeof(query), "select transcript from knownCanonical" + " where '%s' = transcript;", geneName); + struct sqlResult *sr = sqlGetResult(conn, query); + char **row; + if ((row = sqlNextRow(sr)) != NULL) + { + foundIt = TRUE; + } + sqlFreeResult(&sr); + } +return foundIt; +} + static void addKnownGeneItems(struct hgPosTable *table, - struct trixSearchResult *tsrList, struct sqlConnection *conn) + struct trixSearchResult *tsrList, struct sqlConnection *conn, struct sqlConnection *conn2) /* Convert tsrList to posList, and hang posList off of table. */ { /* This code works with just two SQL queries no matter how * big the search result list is. For cases where the search * result list is big (say 100 or 1000 items) this is noticably * faster than the simpler-to-code approach that would do two * queries for each search result. We pay for this speed tweak * by having to construct a more elaborate query, and by having * to maintain a hash to connect the query results back to the * individual positions. */ struct dyString *dy = dyStringNew(0); struct trixSearchResult *tsr; struct hash *hash = hashNew(16); -struct hgPos *posList = NULL, *pos; +struct hgPos *posList = NULL, *pos; // *canonicalPos = NULL; struct tsrPos *tpList = NULL, *tp; struct sqlResult *sr; char **row; int maxToReturn = NONEXHAUSTIVE_SEARCH_LIMIT; if (slCount(tsrList) > maxToReturn) { warn("Search terms are not very specific, only showing first %d matching UCSC Genes.", maxToReturn); tsr = slElementFromIx(tsrList, maxToReturn-1); tsr->next = NULL; } /* Make hash of all search results - one for each known gene ID. */ for (tsr = tsrList; tsr != NULL; tsr = tsr->next) @@ -651,82 +671,132 @@ } sqlFreeResult(&sr); /* Stream through kgXref table adding description and geneSymbol */ dyStringClear(dy); sqlDyStringAppend(dy, "select kgID,geneSymbol,description from kgXref where kgID in ("); for (tsr = tsrList; tsr != NULL; tsr = tsr->next) { sqlDyStringPrintf(dy, "'%s'", tsr->itemId); if (tsr->next != NULL) dyStringAppendC(dy, ','); } dyStringAppend(dy, ")"); sr = sqlGetResult(conn, dy->string); + +// Store all canonical hgPos in a linked list while ((row = sqlNextRow(sr)) != NULL) { tp = hashFindVal(hash, row[0]); if (tp == NULL) internalErr(); for (pos = tp->posList; pos != NULL; pos = pos->next) { char nameBuf[256]; + //char nameBuf2[256]; safef(nameBuf, sizeof(nameBuf), "%s (%s)", row[1], row[0]); pos->name = cloneString(nameBuf); + if (isCanonical(conn2,row[0])) + { + //safef(nameBuf2, sizeof(nameBuf2), "Canonical: %s", nameBuf); + //pos->name = cloneString(nameBuf2); + pos->canonical = TRUE; + } + else{ + pos->canonical = FALSE; + } pos->description = cloneString(row[2]); pos->browserName = cloneString(row[0]); } } sqlFreeResult(&sr); /* Hang all pos onto table. */ for (tp = tpList; tp != NULL; tp = tp->next) { - struct hgPos *next; + struct hgPos *next, *canonicalList = NULL; for (pos = tp->posList; pos != NULL; pos = next) { next = pos->next; slAddHead(&posList, pos); + //uglyAbort("%d", pos->canonical); + if (pos->canonical) + { + //uglyAbort("inside the if statement"); + //slAddHead(&canonicalList, pos); } } + //uglyAbort("%i",slCount(tp->posList)); + /* Pull all canonical genes to the top of the list */ + for (pos = canonicalList ; pos != NULL; pos = next) + { + next = pos->next; + slRemoveEl(&posList, pos); + slAddHead(&posList, pos); + } + + } + +#ifdef OLD +/* Go through list of canoncial genes + * Put them at the top of posList. */ +struct hgPos *next, *canonicalPos = NULL; +for (canonicalPos = canonicalList; canonicalPos!= NULL; canonicalPos = next) + { + uglyAbort("Starting the loop to move canonicals up"); + next = canonicalPos->next; + slRemoveEl(&posList, canonicalPos); + slAddHead(&posList, canonicalPos); + } +/* Move canonical to top of list */ +if (canonicalPos != NULL) + { + slRemoveEl(&posList, canonicalPos); + slAddHead(&posList, canonicalPos); + } +#endif /* OLD */ + table->posList = posList; + hashFree(&hash); dyStringFree(&dy); } boolean findKnownGeneFullText(char *db, char *term,struct hgPositions *hgp) /* Look for position in full text. */ { boolean gotIt = FALSE; struct trix *trix; struct trixSearchResult *tsrList; char *lowered = cloneString(term); char *keyWords[HGFIND_MAX_KEYWORDS]; int keyCount; char *path = makeIndexPath(db); trix = trixOpen(path); tolowers(lowered); keyCount = chopLine(lowered, keyWords); tsrList = trixSearch(trix, keyCount, keyWords, TRUE); if (tsrList != NULL) { struct hgPosTable *table = addKnownGeneTable(db, hgp); struct sqlConnection *conn = hAllocConn(db); - addKnownGeneItems(table, tsrList, conn); + struct sqlConnection *conn2 = hAllocConn(db); + addKnownGeneItems(table, tsrList, conn, conn2); hFreeConn(&conn); + hFreeConn(&conn2); gotIt = TRUE; } freez(&lowered); trixSearchResultFreeList(&tsrList); trixClose(&trix); return gotIt; } static boolean findKnownGeneDescLike(char *db, char *spec, struct hgPositions *hgp, char *tableName) /* Look for position in gene prediction table. */ { struct sqlConnection *conn; struct sqlResult *sr = NULL; struct dyString *query; @@ -2482,36 +2552,42 @@ fprintf(f, "%s=%s&", trackName, vis); // this is magic to tell the browser to make the // composite and this subTrack visible if (tdb->parent) { if (tdbIsSuperTrackChild(tdb)) fprintf(f, "%s=show&", tdb->parent->track); else { // tdb is a subtrack of a composite or a view fprintf(f, "%s_sel=1&", trackName); fprintf(f, "%s_sel=1&", tdb->parent->track); } } fprintf(f, "hgFind.matches=%s,\">", encMatches); + if(pos->canonical) { + fprintf(f, "<B>"); + } htmTextOut(f, pos->name); + if(pos->canonical) { + fprintf(f, "</B>"); + } fprintf(f, " at %s</A>", range); desc = pos->description; if (desc) { - fprintf(f, " - "); + fprintf(f, " -+ "); htmTextOut(f, desc); } fprintf(f, "\n"); freeMem(encMatches); } } if (table->htmlEnd) table->htmlEnd(table, f); else fprintf(f, "</PRE>\n"); } } if(containerDivPrinted) fprintf(f, "</div>\n");