d3aaebb71ef2b82ece4340766c0de67541ce7362
chmalee
  Wed Jul 5 16:41:56 2023 -0700
Fix for multiple hgPcr results feature, actually use the stored primer pair in the psl qName, refs #31608

diff --git src/hg/hgTracks/hgTracks.c src/hg/hgTracks/hgTracks.c
index 7a2b788..7e0f84b 100644
--- src/hg/hgTracks/hgTracks.c
+++ src/hg/hgTracks/hgTracks.c
@@ -820,87 +820,92 @@
 struct linkedFeatures *lf = item;
 return pcrResultItemAccName(lf->name, lf->extra, (struct psl *)lf->original);
 }
 
 void pcrResultLoad(struct track *tg)
 /* Load locations of primer matches into linkedFeatures items. */
 {
 char *pslFileName, *primerFileName;
 struct targetDb *target;
 if (! pcrResultParseCart(database, cart, &pslFileName, &primerFileName, &target))
     return;
 
 /* Don't free psl -- used in drawing phase by baseColor code. */
 struct psl *pslList = pslLoadAll(pslFileName), *psl;
 struct linkedFeatures *itemList = NULL;
-if (target != NULL)
-    {
-    int rowOffset = hOffsetPastBin(database, chromName, target->pslTable);
 struct sqlConnection *conn = hAllocConn(database);
 struct sqlResult *sr;
+for (psl = pslList; psl != NULL; psl = psl->next)
+    {
+    // pcr result matches to a targetDb are of the format transcript__gene
+    if (stringIn("__", psl->tName))
+        {
+        int rowOffset = hOffsetPastBin(database, chromName, target->pslTable);
         char **row;
         char query[2048];
-    struct psl *tpsl;
-    for (tpsl = pslList;  tpsl != NULL;  tpsl = tpsl->next)
-	{
-	char *itemAcc = pcrResultItemAccession(tpsl->tName);
-	char *itemName = pcrResultItemName(tpsl->tName);
+        char *itemAcc = pcrResultItemAccession(psl->tName);
+        char *itemName = pcrResultItemName(psl->tName);
         /* Query target->pslTable to get target-to-genomic mapping: */
         sqlSafef(query, sizeof(query), "select * from %s where qName = '%s'",
               target->pslTable, itemAcc);
         sr = sqlGetResult(conn, query);
         while ((row = sqlNextRow(sr)) != NULL)
             {
             struct psl *gpsl = pslLoad(row+rowOffset);
             if (sameString(gpsl->tName, chromName) && gpsl->tStart < winEnd && gpsl->tEnd > winStart)
                 {
-		struct psl *trimmed = pslTrimToQueryRange(gpsl, tpsl->tStart,
-				      tpsl->tEnd);
+                struct psl *trimmed = pslTrimToQueryRange(gpsl, psl->tStart,
+                              psl->tEnd);
                 struct linkedFeatures *lf;
                 char *targetStyle = cartUsualString(cart,
                      PCR_RESULT_TARGET_STYLE, PCR_RESULT_TARGET_STYLE_DEFAULT);
                 if (sameString(targetStyle, PCR_RESULT_TARGET_STYLE_TALL))
                     {
                     lf = lfFromPslx(gpsl, 1, FALSE, FALSE, tg);
                     lf->tallStart = trimmed->tStart;
                     lf->tallEnd = trimmed->tEnd;
                     }
                 else
                     {
                     lf = lfFromPslx(trimmed, 1, FALSE, FALSE, tg);
                     }
                 lf->name = cloneString(itemAcc);
                 char extraInfo[512];
                 safef(extraInfo, sizeof(extraInfo), "%s|%d|%d",
-		      (itemName ? itemName : ""), tpsl->tStart, tpsl->tEnd);
+                      (itemName ? itemName : ""), psl->tStart, psl->tEnd);
                 lf->extra = cloneString(extraInfo);
+                        // now that there may be more than one primer pair result
+                        // in the pcrResults list, we need make sure we are using the
+                        // right primer pair later
+                        ((struct psl *)(lf->original))->qName = cloneString(psl->qName);
                 slAddHead(&itemList, lf);
                 }
             }
         }
-    hFreeConn(&conn);
-    }
     else
-    for (psl = pslList;  psl != NULL;  psl = psl->next)
+        {
         if (sameString(psl->tName, chromName) && psl->tStart < winEnd && psl->tEnd > winStart)
             {
             struct linkedFeatures *lf = lfFromPslx(psl, 1, FALSE, FALSE, tg);
             lf->name = cloneString("");
             lf->extra = cloneString("");
             lf->original = psl;
             slAddHead(&itemList, lf);
             }
+        }
+    }
+hFreeConn(&conn);
 slSort(&itemList, linkedFeaturesCmp);
 tg->items = itemList;
 }
 
 char *pcrResultTrackItemName(struct track *tg, void *item)
 /* If lf->extra is non-empty, return it (display name for item).
  * Otherwise default to item name. */
 {
 struct linkedFeatures *lf = item;
 char *extra = (char *)lf->extra;
 if (isNotEmpty(extra))
     {
     static char displayName[512];
     safecpy(displayName, sizeof(displayName), extra);
     char *ptr = strchr(displayName, '|');