3e70e7601a08e28667531d5abe3fe8b04ee95ded
chmalee
  Fri Jul 16 11:23:58 2021 -0700
Return multiple transcripts for pseudo hgvs search, refs #15554

diff --git src/hg/lib/hgFind.c src/hg/lib/hgFind.c
index df2add9..7a96842 100644
--- src/hg/lib/hgFind.c
+++ src/hg/lib/hgFind.c
@@ -2717,74 +2717,95 @@
     if (hfs != NULL)
 	foundIt = hgFindUsingSpec(cart, db, hfs, term, limitResults, hgp, FALSE, 0,0, FALSE);
     else
 	warn("Unrecognized singleSearch=%s in URL", search);
     }
 if (foundIt)
     {
     fixSinglePos(hgp);
     if (cart != NULL)
         cartSetString(cart, "hgFind.matches", hgp->tableList->posList->browserName);
     }
 return foundIt;
 }
 
 static boolean matchesHgvs(struct cart *cart, char *db, char *term, struct hgPositions *hgp)
-/* Return TRUE if the search term looks like a variant encoded using the HGVS nomenclature */
-/* See http://varnomen.hgvs.org/ */
+/* Return TRUE if the search term looks like a variant encoded using the HGVS nomenclature
+ * See http://varnomen.hgvs.org/
+ * If search term is a pseudo hgvs term like GeneName AminoAcidPosition (RUNX2 Arg155) and
+ * matches more than one transcript, fill out the hgp with the potential matches so the user
+ * can choose where to go, otherwise return a singlePos */
 {
 boolean foundIt = FALSE;
-struct hgvsVariant *hgvs = hgvsParseTerm(term);
-if (hgvs == NULL)
-    hgvs = hgvsParsePseudoHgvs(db, term);
-if (hgvs)
+struct hgvsVariant *hgvsList = hgvsParseTerm(term);
+if (hgvsList == NULL)
+    hgvsList = hgvsParsePseudoHgvs(db, term);
+if (hgvsList)
     {
+    struct hgvsVariant *hgvs = NULL;
+    int hgvsListLen = slCount(hgvs);
+    struct hgPosTable *table;
+    AllocVar(table);
+    table->description = "HGVS";
     struct dyString *dyWarn = dyStringNew(0);
+    for (hgvs = hgvsList; hgvs != NULL; hgvs = hgvs->next)
+        {
         char *pslTable = NULL;
         struct bed *mapping = hgvsValidateAndMap(hgvs, db, term, dyWarn, &pslTable);
-    if (dyStringLen(dyWarn) > 0)
+        if (hgvsListLen == 1 && dyStringLen(dyWarn) > 0)
             warn("%s", dyStringContents(dyWarn));
         if (mapping)
             {
             int padding = 5;
             char *trackTable;
             if (isEmpty(pslTable))
                 trackTable = "chromInfo";
             else if (startsWith("lrg", pslTable))
                 trackTable = "lrgTranscriptAli";
             else if (startsWith("wgEncodeGencode", pslTable))
                 trackTable = pslTable;
             else if (startsWith("ncbiRefSeqPsl", pslTable))
                 {
                 if (startsWith("NM_", hgvs->seqAcc) || startsWith("NR_", hgvs->seqAcc) ||
                     startsWith("NP_", hgvs->seqAcc) || startsWith("YP_", hgvs->seqAcc))
                     trackTable = "ncbiRefSeqCurated";
                 else if (startsWith("XM_", hgvs->seqAcc) || startsWith("XR_", hgvs->seqAcc) ||
                          startsWith("XP_", hgvs->seqAcc))
                     trackTable = "ncbiRefSeqPredicted";
                 else
                     trackTable = "ncbiRefSeq";
                 }
             else
                 trackTable = "refGene";
-        singlePos(hgp, "HGVS", NULL, trackTable, term, "",
-                  mapping->chrom, mapping->chromStart-padding, mapping->chromEnd+padding);
+            if (hgp->tableList == NULL)
+                hgp->tableList = table;
+            table->name = trackTable;
+            struct hgPos *pos;
+            AllocVar(pos);
+            pos->chrom = mapping->chrom;
+            pos->chromStart = mapping->chromStart-padding;
+            pos->chromEnd = mapping->chromEnd+padding;
+            pos->name = cloneString(hgvs->seqAcc);
+            pos->description = cloneString(term);
+            pos->browserName = "";
+            slAddHead(&table->posList, pos);
             // highlight the mapped bases to distinguish from padding
             hgp->tableList->posList->highlight = addHighlight(db, mapping->chrom,
                                                     mapping->chromStart, mapping->chromEnd);
             foundIt = TRUE;
             }
+        }
     dyStringFree(&dyWarn);
     }
 return foundIt;
 }
 
 struct hgPositions *hgPositionsFind(char *db, char *term, char *extraCgi,
 	char *hgAppNameIn, struct cart *cart, boolean multiTerm)
 /* Return container of tracks and positions (if any) that match term. */
 {
 struct hgPositions *hgp = NULL, *hgpItem = NULL;
 regmatch_t substrs[4];
 boolean canonicalSpec = FALSE;
 boolean gbrowserSpec = FALSE;
 boolean lengthSpec = FALSE;
 boolean singleBaseSpec = FALSE;