63890999edbfdac428544f159a33e503618ca7f8
angie
  Wed Jan 7 13:56:43 2026 -0800
Add support for vai.pl to accept a GenArk assembly accession as db, and for hgVai to accept a geneTrack without the hub_number_ prefix when db is a hub.

diff --git src/hg/hgVai/hgVai.c src/hg/hgVai/hgVai.c
index 99ed8d8af10..31d244dc35a 100644
--- src/hg/hgVai/hgVai.c
+++ src/hg/hgVai/hgVai.c
@@ -2847,50 +2847,74 @@
         tag = "REFSEQ_STATUS";
         description = "<A HREF=" REFSEQ_STATUS_DOC_URL " "
          "TARGET=_BLANK>RefSeq status</A> of the transcript";
         }
     else
         {
         errAbort("addTxStatusExtras: Unrecognized {table,field}: {%s,%s}",
                  txStatDtf->table, txStatDtf->field);
         }
     char *column = annoStreamDbColumnNameFromDtf(database, geneTrack, txStatDtf);
     annoFormatVepAddExtraItem(vepOut, (struct annoStreamer *)gpVarGrator,
                               tag, description, column, isBoolean);
     }
 }
 
+static char *getHubPrefix(char *dbOrTrack)
+/* Extract the hub_number_ prefix from a db or track identifier, allocate & return. */
+{
+if (!startsWith(hubTrackPrefix, dbOrTrack))
+    {
+    errAbort("getHubPrefix: '%s' does not start with the expected prefix '%s'", dbOrTrack, hubTrackPrefix);
+    }
+uint hubNumber = atoll(dbOrTrack + strlen(hubTrackPrefix));
+struct dyString *dy = dyStringCreate("%s%u_", hubTrackPrefix, hubNumber);
+return dyStringCannibalize(&dy);
+}
+
 void doQuery()
 /* Translate simple form inputs into anno* components and execute query. */
 {
 dyInfo = dyStringNew(0);
 char *chrom = NULL;
 uint start = 0, end = 0;
 if (sameString(regionType, hgvaRegionTypeRange))
     getCartPosOrDie(&chrom, &start, &end);
 struct annoAssembly *assembly = hAnnoGetAssembly(database);
 boolean isCommandLine = (cgiOptionalString("cgiSpoof") != NULL);
 
 char *geneTrack = cartString(cart, "hgva_geneTrack");
 struct trackDb *geneTdb = tdbForTrack(database, geneTrack, &fullTrackList);
+if (geneTdb == NULL)
+    {
+    if (startsWith(hubTrackPrefix, database) && !startsWith(hubTrackPrefix, geneTrack))
+        {
+        // geneTrack was provided without the hub_ prefix, try adding prefix and looking it up
+        char *hubNumberPrefix = getHubPrefix(database);
+        struct dyString *dy = dyStringCreate("%s%s", hubNumberPrefix, geneTrack);
+        geneTdb = tdbForTrack(database, dy->string, &fullTrackList);
+        if (geneTdb != NULL)
+            geneTrack = dyStringCannibalize(&dy);
+        }
     if (geneTdb == NULL)
         {
         warn("Can't find tdb for gene track %s", geneTrack);
         if (! isCommandLine)
             doUi();
         return;
         }
+    }
 
 int maxVarRows = cartUsualInt(cart, "hgva_variantLimit", 10);
 struct annoStreamer *primary = NULL;
 char *primaryLongLabel = NULL;
 char *variantTrack = cartString(cart, "hgva_variantTrack");
 struct slName *commentList = NULL;
 if (sameString(variantTrack, hgvaSampleVariants))
     {
     primary = makeSampleVariantsStreamer(assembly, geneTdb, maxVarRows);
     primaryLongLabel = hgvaSampleVariantsLabel;
     // Sample variants can't always be made within the currently selected position range,
     // so just for these, force search to be genome-wide.
     chrom = NULL;
     start = 0;
     end = 0;