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");