743f1e268d2f3f658a48309a72227ce9fce85c97
angie
  Fri Apr 3 16:43:57 2015 -0700
Added a special annoStreamer for knownGene, to tack on kgXref.geneSymbol
at the end.  Now in hgVai, the geneSymbol is shown instead of the protein ID.
The new column is also available in hgIntegrator.  Now users can get the
gene symbol that goes with their items, without changing gene track.
refs #11752 #14579

diff --git src/hg/lib/hAnno.c src/hg/lib/hAnno.c
index 6e7fd7e..e6512d5 100644
--- src/hg/lib/hAnno.c
+++ src/hg/lib/hAnno.c
@@ -6,30 +6,31 @@
 #include "customTrack.h"
 #include "grp.h"
 #include "hdb.h"
 #include "hubConnect.h"
 #include "hui.h"
 #include "jksql.h"
 #include "pgSnp.h"
 #include "trackHub.h"
 #include "vcf.h"
 #include "annoGratorQuery.h"
 #include "annoGratorGpVar.h"
 #include "annoStreamBigBed.h"
 #include "annoStreamBigWig.h"
 #include "annoStreamDb.h"
 #include "annoStreamDbFactorSource.h"
+#include "annoStreamDbKnownGene.h"
 #include "annoStreamTab.h"
 #include "annoStreamVcf.h"
 #include "annoStreamWig.h"
 #include "annoGrateWigDb.h"
 #include "annoFormatTab.h"
 #include "annoFormatVep.h"
 
 //#*** duplicated in hgVarAnnoGrator and annoGratorTester
 struct annoAssembly *hAnnoGetAssembly(char *db)
 /* Make annoAssembly for db. */
 {
 static struct annoAssembly *aa = NULL;
 if (aa == NULL)
     {
     if (trackHubDatabase(db))
@@ -179,31 +180,38 @@
     char *fileOrUrl = getBigDataFileName(dataDb, tdb, selTable, chrom);
     streamer = annoStreamBigBedNew(fileOrUrl, assembly, maxOutRows);
     }
 else if (startsWith("bigWig", tdb->type))
     {
     char *fileOrUrl = getBigDataFileName(dataDb, tdb, selTable, chrom);
     streamer = annoStreamBigWigNew(fileOrUrl, assembly); //#*** no maxOutRows support
     }
 else if (sameString("factorSource", tdb->type))
     {
     char *sourceTable = trackDbSetting(tdb, "sourceTable");
     char *inputsTable = trackDbSetting(tdb, "inputTrackTable");
     streamer = annoStreamDbFactorSourceNew(dataDb, tdb->track, sourceTable, inputsTable, assembly,
 					   maxOutRows);
     }
-else
+else if (sameString("knownGene", tdb->track))
+    {
+    struct sqlConnection *conn = hAllocConn(dataDb);
+    if (sqlTableExists(conn, "knownGene") && sqlTableExists(conn, "kgXref"))
+        streamer = annoStreamDbKnownGeneNew(dataDb, assembly, maxOutRows);
+    hFreeConn(&conn);
+    }
+if (streamer == NULL)
     {
     struct sqlConnection *conn = hAllocConn(dataDb);
     char maybeSplitTable[1024];
     if (sqlTableExists(conn, dbTable))
 	safecpy(maybeSplitTable, sizeof(maybeSplitTable), dbTable);
     else
 	safef(maybeSplitTable, sizeof(maybeSplitTable), "%s_%s", chrom, dbTable);
     hFreeConn(&conn);
     struct asObject *asObj = getAutoSqlForTable(dataDb, maybeSplitTable, tdb, TRUE);
     streamer = annoStreamDbNew(dataDb, maybeSplitTable, assembly, asObj, maxOutRows);
     }
 return streamer;
 }
 
 struct annoGrator *hAnnoGratorFromBigFileUrl(char *fileOrUrl, struct annoAssembly *assembly,
@@ -274,30 +282,37 @@
     asObj = pgSnpAsObj();
 else if (sameString("bam", tdb->type) || sameString("maf", tdb->type))
     warn("Sorry, %s is not yet supported", tdb->type);
 else if (startsWithWord("bed", tdb->type) && !strchr(tdb->type, '+'))
     {
     // BED with no + fields; parse bed field count out of type line.
     int bedFieldCount = 3;
     char typeCopy[PATH_LEN];
     safecpy(typeCopy, sizeof(typeCopy), tdb->type);
     char *words[8];
     int wordCount = chopLine(typeCopy, words);
     if (wordCount > 1)
         bedFieldCount = atoi(words[1]);
     asObj = asParseText(bedAsDef(bedFieldCount, bedFieldCount));
     }
+else if (sameString(tdb->track, "knownGene"))
+    {
+    struct sqlConnection *conn = hAllocConn(db);
+    if (sqlTableExists(conn, "knownGene") && sqlTableExists(conn, "kgXref"))
+        asObj = annoStreamDbKnownGeneAsObj();
+    hFreeConn(&conn);
+    }
 return asObj;
 }
 
 struct asObject *hAnnoGetAutoSqlForTdb(char *db, char *chrom, struct trackDb *tdb)
 /* If possible, return the asObj that a streamer for this track would use, otherwise NULL. */
 {
 struct asObject *asObj = getAutoSqlForType(db, chrom, tdb);
 
 if (!asObj && !isHubTrack(tdb->track))
     {
     // If none of the above, it must be a database table; deduce autoSql from sql fields.
     char *dataDb = db, *dbTable = tdb->table;
     if (isCustomTrack(tdb->track))
         {
         dbTable = trackDbSetting(tdb, "dbTableName");