2de160a334786c2168e379c5f02838f4aed40a3b chmalee Thu Jul 27 12:20:35 2023 -0700 Fix two separate hgPcr related bugs. One, the primers entered by the user do not have to match the genome/transcript fully, and so when looking up the primers for showing mismatches we need to ensure we find them by relying on the psl qName rather than the primer file that holds the users input. Second, when clicking through to hgc, ensure that we check that the tStart and tEnd of the psl match what was clicked on so the right amplicon sequence can be shown, in the case that two separate searches that hit the same transcript are visible, refs #31784 diff --git src/hg/hgc/hgc.c src/hg/hgc/hgc.c index 29952ed..4365a9b 100644 --- src/hg/hgc/hgc.c +++ src/hg/hgc/hgc.c @@ -7084,104 +7084,107 @@ 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) +static void pslFileGetPrimers(char *pslFileName, char *transcript, int ampStart, int ampEnd, + 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)) + if (sameString(psl->tName, target) && ampStart == psl->tStart && ampEnd == psl->tEnd) { 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 = NULL, *rPrimer = NULL; +int ampStart, ampEnd; +char *targetSeqName = NULL; boolean targetSearch = stringIn("__", item) != 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); + targetSeqName = words[0]; + if (endsWith(targetSeqName, "__")) + targetSeqName[strlen(targetSeqName)-2] = '\0'; + ampStart = atoi(words[1]), ampEnd = atoi(words[2]); // use the psl file to find the right primer pair - pslFileGetPrimers(pslFileName, item, &fPrimer, &rPrimer); + pslFileGetPrimers(pslFileName, item, ampStart, ampEnd, &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); } } 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 (targetSearch) printf("<B>Search target:</B> %s<BR>\n", target->description); struct psl *itemPsl = NULL, *otherPsls = NULL, *psl; 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, fPrimer, rPrimer); printPcrTargetMatch(target, itemPsl, TRUE); } else { pcrResultGetPsl(pslFileName, NULL, item, seqName, cartInt(cart, "o"), cartInt(cart, "t"), &itemPsl, &otherPsls, fPrimer, rPrimer); printPosOnChrom(itemPsl->tName, itemPsl->tStart, itemPsl->tEnd, itemPsl->strand, FALSE, NULL); } if (otherPsls != NULL) {