6f2531a141428b3238607e9f1c74f7bb127bf38e
ceisenhart
  Wed Nov 12 15:45:45 2014 -0800
Canonical genes are brought to the top of the search result
diff --git src/hg/lib/hgFind.c src/hg/lib/hgFind.c
index eb415c1..903352e 100644
--- src/hg/lib/hgFind.c
+++ src/hg/lib/hgFind.c
@@ -596,46 +596,61 @@
     {
     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 int hgPosCmpCanonical(const void *vhg1, const void *vhg2)
+// Compares two hgPos structs and returns an integer
+{
+const struct hgPos *hg1 = *((struct hgPos**)vhg1);
+const struct hgPos *hg2 = *((struct hgPos**)vhg2);
+int diff = trixSearchResultCmp(&hg1->tp->tsr, &hg2->tp->tsr);
+if (diff == 0)
+    {
+    diff = (hg2->canonical - hg1->canonical);
+    }
+return diff;
+}
+
+
 static void addKnownGeneItems(struct hgPosTable *table,
 	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; // *canonicalPos = NULL;
+struct hgPos *pos, *posList = 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)
@@ -645,129 +660,96 @@
     slAddHead(&tpList, tp);
     hashAdd(hash, tsr->itemId, tp);
     }
 
 /* Stream through knownGenes table and make up a pos
  * for each mapping of each gene matching search. */
 sqlDyStringAppend(dy, 
 	"select name,chrom,txStart,txEnd from knownGene where name 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);
+
 while ((row = sqlNextRow(sr)) != NULL)
     {
     tp = hashFindVal(hash, row[0]);
     if (tp == NULL)
         internalErr();
     AllocVar(pos);
     pos->chrom = cloneString(row[1]);
     pos->chromStart = sqlUnsigned(row[2]);
     pos->chromEnd = sqlUnsigned(row[3]);
+    pos->tp = tp;
     slAddHead(&tp->posList, pos);
     }
 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, *canonicalList = NULL;
+    struct hgPos *next;
     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 */
-
+slSort(&posList, hgPosCmpCanonical);
 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;
@@ -1317,45 +1299,30 @@
 fprintf(f, "------------------------------------------------------------------------------\n");
 }
 
 static void mrnaHtmlEnd(struct hgPosTable *table, FILE *f)
 /* Print end to mrna alignment positions. */
 {
 fprintf(f, "</PRE>");
 }
 
 static void mrnaHtmlOnePos(struct hgPosTable *table, struct hgPos *pos, FILE *f)
 /* Print one mrna alignment position. */
 {
 fprintf(f, "%s", pos->description);
 }
 
-#ifdef OLD
-static void makeGbTrackTableName(char *db, char *tableName, size_t tnSize, char *base)
-/* Now we have to watch out for scaffold-based browsers where 
- * the track is all_{mrna,est} not {mrna,est}. */
-{
-char splitTable[256];
-safef(splitTable, sizeof(splitTable), "%s_%s",
-      hDefaultChrom(db), base);
-if (hTableExists(db, splitTable))
-    safef(tableName, tnSize, "%s", base);
-else
-    safef(tableName, tnSize, "all_%s", base);
-}
-#endif /* OLD */
-
 char *hCarefulTrackOpenVis(char *db, char *trackName)
 /* If track is already in full mode, return full; otherwise, return
  * hTrackOpenVis. */
 {
 char *vis = cart ? cartOptionalString(cart, trackName) : NULL;
 if (vis && sameString(vis, "full"))
     return "full";
 else
     return hTrackOpenVis(db, trackName);
 }
 
 static struct psl *getPslFromTable(struct sqlConnection *conn, char *db, char *table, char *acc)
 /* If table exists, return PSL for each row with qName = acc. */
 {
 struct psl *pslList = NULL;