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/hgc/hgc.c src/hg/hgc/hgc.c
index 2d4b10c..c8ca223 100644
--- src/hg/hgc/hgc.c
+++ src/hg/hgc/hgc.c
@@ -7024,40 +7024,40 @@
 pslFree(&itemPsl);
 pslFreeList(&otherPsls);
 }
 
 static void upperMatch(char *dna, char *primer, int size)
 /* Uppercase DNA where it matches primer. -- copied from gfPcrLib.c. */
 {
 int i;
 for (i=0; i<size; ++i)
     {
     if (dna[i] == primer[i])
         dna[i] = toupper(dna[i]);
     }
 }
 
-void printPcrSequence(struct targetDb *target, struct psl *psl,
+void printPcrSequence(char *item, struct targetDb *target, struct psl *psl,
 		      char *fPrimer, char *rPrimer)
 /* Print the amplicon sequence (as on hgPcr results page). */
 {
 int productSize = psl->tEnd - psl->tStart;
 char *ffPrimer = cloneString(fPrimer);
 char *rrPrimer = cloneString(rPrimer);
 int rPrimerSize = strlen(rPrimer);
 struct dnaSeq *seq;
-if (target != NULL)
+if (stringIn("__", item) && target != NULL)
     {
     /* Use seq+extFile if specified; otherwise just retrieve from seqFile. */
     if (isNotEmpty(target->seqTable) && isNotEmpty(target->extFileTable))
 	{
 	struct sqlConnection *conn = hAllocConn(database);
 	seq = hDnaSeqGet(database, psl->tName, target->seqTable,
 			 target->extFileTable);
 	hFreeConn(&conn);
 	char *dna = cloneStringZ(seq->dna + psl->tStart, productSize);
 	freeMem(seq->dna);
 	seq->dna = dna;
 	}
     else
 	{
 	struct twoBitFile *tbf = twoBitOpen(target->seqFile);
@@ -7084,102 +7084,133 @@
        productSize, fPrimer, rPrimer);
 
 /* Flip reverse primer to be in same direction and case as sequence, to
  * compare with sequence: */
 reverseComplement(rrPrimer, rPrimerSize);
 tolowers(rrPrimer);
 tolowers(ffPrimer);
 
 /* Capitalize where sequence and primer match, and write out sequence. */
 upperMatch(dna, ffPrimer, strlen(ffPrimer));
 upperMatch(dna + productSize - rPrimerSize, rrPrimer, rPrimerSize);
 faWriteNext(stdout, NULL, dna, productSize);
 printf("</PRE></TT>");
 }
 
+static void pslFileGetPrimers(char *pslFileName, char *transcript, char **retFPrimer, char **retRPrimer)
+/* Use a psl file to get primers associated with the transcript */
+{
+char *pslFields[21];
+struct lineFile *lf = lineFileOpen(pslFileName, TRUE);
+char *target = cloneString(transcript);
+char *pipe = strchr(target, '|');
+*pipe = '\0';
+while (lineFileRow(lf, pslFields))
+    {
+    struct psl *psl = pslLoad(pslFields);
+    if (sameString(psl->tName, target))
+        {
+        char *pair = psl->qName;
+        char *under = strchr(pair, '_');
+        *under = '\0';
+        *retFPrimer = cloneString(pair);
+        *retRPrimer = cloneString(under+1);
+        break;
+        }
+    }
+lineFileClose(&lf);
+}
+
 void doPcrResult(char *track, char *item)
 /* Process click on PCR of user's primers. */
 {
 struct trackDb *tdb = pcrResultFakeTdb();
 char *pslFileName, *primerFileName;
 struct targetDb *target;
 cartWebStart(cart, database, "PCR Results");
 if (! pcrResultParseCart(database, cart, &pslFileName, &primerFileName, &target))
     errAbort("PCR Result track has disappeared!");
 
 char *fPrimer, *rPrimer;
+boolean targetSearch = stringIn("__", item) != NULL;
+if (targetSearch)
+    {
+    // use the psl file to find the right primer pair
+    pslFileGetPrimers(pslFileName, item, &fPrimer, &rPrimer);
+    }
+else
+    {
     // the item name contains the forward and reverse primers
     int maxSplits = 2;
     char *splitQName[maxSplits];
     int numSplits = chopString(cloneString(item), "_", splitQName, sizeof(splitQName));
     if (numSplits == maxSplits)
         {
         fPrimer = splitQName[0];
         touppers(fPrimer);
         rPrimer = splitQName[1];
         touppers(rPrimer);
         }
-else
-    pcrResultGetPrimers(primerFileName, &fPrimer, &rPrimer);
+    }
 printf("<H2>PCR Results (<TT>%s %s</TT>)</H2>\n", fPrimer, rPrimer);
 printf("<B>Forward primer:</B> 5' <TT>%s</TT> 3'<BR>\n", fPrimer);
 printf("<B>Reverse primer:</B> 5' <TT>%s</TT> 3'<BR>\n", rPrimer);
-if (target != NULL)
+if (targetSearch)
     printf("<B>Search target:</B> %s<BR>\n", target->description);
 
 struct psl *itemPsl = NULL, *otherPsls = NULL, *psl;
-if (target != NULL)
+if (targetSearch)
     {
     /* item (from hgTracks) is |-separated: target sequence name,
      * amplicon start offset in target sequence, and amplicon end offset. */
     char *words[3];
     int wordCount = chopByChar(cloneString(item), '|', words, ArraySize(words));
     if (wordCount != 3)
 	errAbort("doPcrResult: expected 3 |-sep'd words but got '%s'", item);
     char *targetSeqName = words[0];
     if (endsWith(targetSeqName, "__"))
 	targetSeqName[strlen(targetSeqName)-2] = '\0';
     int ampStart = atoi(words[1]), ampEnd = atoi(words[2]);
     pcrResultGetPsl(pslFileName, target, targetSeqName, seqName, ampStart, ampEnd,
-		    &itemPsl, &otherPsls);
+		    &itemPsl, &otherPsls, fPrimer, rPrimer);
     printPcrTargetMatch(target, itemPsl, TRUE);
     }
 else
     {
-    pcrResultGetPsl(pslFileName, target, item,
+    pcrResultGetPsl(pslFileName, NULL, item,
 		    seqName, cartInt(cart, "o"), cartInt(cart, "t"),
-		    &itemPsl, &otherPsls);
+		    &itemPsl, &otherPsls, fPrimer, rPrimer);
     printPosOnChrom(itemPsl->tName, itemPsl->tStart, itemPsl->tEnd,
 		    itemPsl->strand, FALSE, NULL);
     }
 
 if (otherPsls != NULL)
     {
     puts("<HR>");
     printf("<B>Other matches for these primers:</B><BR>\n");
     for (psl = otherPsls;  psl != NULL;  psl = psl->next)
 	{
 	puts("<BR>");
 	if (target != NULL)
 	    printPcrTargetMatch(target, psl, FALSE);
 	else
 	    printPosOnChrom(psl->tName, psl->tStart, psl->tEnd,
 			    psl->strand, FALSE, NULL);
 	}
     puts("<HR>");
     }
-printPcrSequence(target, itemPsl, fPrimer, rPrimer);
+printPcrSequence(item, target, itemPsl, fPrimer, rPrimer);
 
 puts("<BR><HR>");
 printTrackHtml(tdb);
 }
 
 void doUserPsl(char *track, char *item)
 /* Process click on user-defined alignment. */
 {
 int start = cartInt(cart, "o");
 struct lineFile *lf;
 struct psl *pslList = NULL, *psl;
 char *pslName, *faName, *qName;
 enum gfType qt, tt;
 
 cartWebStart(cart, database, "BLAT Search Alignments");