310239836c4e2d37f470c98ca7f544dedceca60c
galt
  Wed Apr 30 14:55:06 2025 -0700
fixes hgBlat table of alignments not available once browsing. This fixes both native blat track and ct blat track. fixes #32750

diff --git src/hg/hgc/hgc.c src/hg/hgc/hgc.c
index dab9628856a..0c83ee861bb 100644
--- src/hg/hgc/hgc.c
+++ src/hg/hgc/hgc.c
@@ -3409,83 +3409,116 @@
                 printIframe(tdb, itemForUrl);
             printPos(seqName, ivStart, ivEnd, strand, FALSE, item);
             int printCount = extraFieldsPrint(tdb,NULL,extraFields, extraFieldCount);
             printCount += 0;
             }
         }
     }
 
 char *bedRow[32];
 char startBuf[16], endBuf[16];
 
 int lastChromId = -1;
 char chromName[bbi->chromBpt->keySize+1];
 
 boolean firstTime = TRUE;
+struct hash *seqHash = hashNew(0);
+struct dyString *sequencesText = dyStringNew(256);
+int sequencesFound = 0;
 for (bb = bbList; bb != NULL; bb = bb->next)
     {
     bbiCachedChromLookup(bbi, bb->chromId, lastChromId, chromName, sizeof(chromName));
 
     lastChromId=bb->chromId;
     bigBedIntervalToRow(bb, chromName, startBuf, endBuf, bedRow, 4);
     if (showEvery || sameString(bedRow[3], item))
 	{
         char *cdsStr, *seq;
         struct psl *psl= getPslAndSeq(tdb, chromName, bb, seqTypeField, &seq, &cdsStr);
         slAddHead(&pslList, psl);
 
         // we're assuming that if there are multiple psl's with the same id that
         // they are the same query sequence so we only put out one set of sequences
-        if (differentString(item, "PrintAllSequences") && firstTime && !isEmpty(seq))    // if there is a query sequence
+        if (!hashLookup(seqHash, bedRow[3]) && !isEmpty(seq))    // if there is a query sequence
+            {
+            if (firstTime)
 		{
 		firstTime = FALSE;
 		printf("<H3>Links to sequence:</H3>\n");
 		printf("<UL>\n");
+		}
 
             if (!isEmpty(cdsStr))  // if we have CDS 
                 {
                 puts("<LI>\n");
-                hgcAnchorSomewhere("htcTranslatedBigPsl", item, "translate", seqName);
+                hgcAnchorSomewhere("htcTranslatedBigPsl", bedRow[3], "translate", seqName);
+		if (showEvery)
+		    printf("Translated Amino Acid Sequence</A> from Query Sequence %s\n", bedRow[3]);
+		else
 		    printf("Translated Amino Acid Sequence</A> from Query Sequence\n");
                 puts("</LI>\n");
                 }
 
 	    if (psl->qSize <= MAX_DISPLAY_QUERY_SEQ_SIZE)
 		{
 		puts("<LI>\n");
-		hgcAnchorSomewhere("htcBigPslSequence", item, tdb->track, seqName);
+		hgcAnchorSomewhere("htcBigPslSequence", bedRow[3], tdb->track, seqName);
+		if (showEvery)
+		    printf("Query Sequence %s</A> \n", bedRow[3]);
+		else
 		    printf("Query Sequence</A> \n");
 		puts("</LI>\n");
-		printf("</UL>\n");
 		}
+
+            hashAdd(seqHash, bedRow[3], "");
+	    dyStringPrintf(sequencesText, ">%s\n%s\n\n", bedRow[3], seq);
+	    ++sequencesFound;
+
             }
 	}
+    if (!showEvery && !firstTime)
+	break;
     }
+if (!firstTime)
+    printf("</UL>\n");
+freeHash(&seqHash);
 
 char *sort = cartUsualString(cart, "sort", pslSortList[0]);
 pslSortListByVar(&pslList, sort);
 
 if (showEvery)
     printf("<H3>Genomic Alignments</H3>");
 else
     printf("<H3>%s/Genomic Alignments</H3>", item);
 if (showEvery || pslIsProtein(pslList))
     printAlignmentsSimple(pslList, start, "htcBigPslAli", tdb->table, item);
 else
     printAlignmentsExtra(pslList, start, "htcBigPslAli", "htcBigPslAliInWindow",
         tdb->table, item);
 pslFreeList(&pslList);
+
+
+if (showEvery && sequencesFound > 0)
+    {  
+    printf("<BR>\n");
+    printf("Input Sequences:<BR>\n");
+    printf("<textarea rows='8' cols='60'>\n");
+    printf("%s", sequencesText->string);
+    printf("</textarea>\n");
+    dyStringFree(&sequencesText);
+    }
+
 printItemDetailsHtml(tdb, item);
 }
 
 void genericPslClick(struct sqlConnection *conn, struct trackDb *tdb,
                      char *item, int start, char *subType)
 /* Handle click in generic psl track. */
 {
 struct psl* pslList = getAlignments(conn, tdb->table, item);
 
 /* check if there is an alignment available for this sequence.  This checks
  * both genbank sequences and other sequences in the seq table.  If so,
  * set it up so they can click through to the alignment. */
 if (hGenBankHaveSeq(database, item, NULL))
     {
     printf("<H3>%s/Genomic Alignments</H3>", item);
@@ -7328,51 +7361,93 @@
     }
 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;
+boolean isProt;
 
 cartWebStart(cart, database, "BLAT Search Alignments");
+
 printf("<H2>BLAT Search Alignments</H2>\n");
-printf("<H3>Click on a line to see detailed letter-by-letter display</H3>");
+printf("<A href id='hgUsualPslShowAllLink'>Show All</A>\n");
+printf("<H3>Click on a line to see detailed letter-by-letter display</H3>\n");
+
+printf("<div id=hgUsualPslShowItem style='display: block'>\n");
 parseSs(item, &pslName, &faName, &qName);
 pslxFileOpen(pslName, &qt, &tt, &lf);
 while ((psl = pslNext(lf)) != NULL)
     {
     if (sameString(psl->qName, qName))
 	{
 	slAddHead(&pslList, psl);
 	}
     else
 	{
 	pslFree(&psl);
 	}
     }
-slSort(&pslList, pslCmpScore);
+slSort(&pslList, pslCmpQueryScore);
 lineFileClose(&lf);
 printAlignments(pslList, start, "htcUserAli", "user", item);
 pslFreeList(&pslList);
+printf("</div>\n");
+
+
+printf("<div id=hgUsualPslShowAll style='display: none'>\n");
+// get hidden rest of alignments.
+pslxFileOpen(pslName, &qt, &tt, &lf);
+isProt = (qt == gftProt);
+while ((psl = pslNext(lf)) != NULL)
+    {
+    slAddHead(&pslList, psl);
+    }
+slSort(&pslList, pslCmpQueryScore);
+lineFileClose(&lf);
+printAlignments(pslList, start, "htcUserAli", "user", "");
+pslFreeList(&pslList);
+
+printf("<BR>\n");
+printf("Input Sequences:<BR>\n");
+printf("<textarea rows='8' cols='60'>\n");
+struct dnaSeq *oSeq, *oSeqList = faReadAllSeq(faName, !isProt);
+for (oSeq = oSeqList; oSeq != NULL; oSeq = oSeq->next)
+    {
+    printf(">%s\n",oSeq->name);
+    printf("%s\n",oSeq->dna);
+    printf("\n");
+    }
+printf("</textarea>\n");
+
+printf("</div>\n");
+
+jsInline("$('#hgUsualPslShowAllLink').click(function(){\n"
+	"  $('#hgUsualPslShowItem')[0].style.display = 'none';\n"
+	"  $('#hgUsualPslShowAll')[0].style.display = 'block';\n"
+	"  $('#hgUsualPslShowAllLink')[0].style.display = 'none';\n"
+	"return false;\n"
+	"});\n");
+
 webIncludeHelpFile(USER_PSL_TRACK_NAME, TRUE);
 }
 
 void doHgGold(struct trackDb *tdb, char *fragName)
 /* Click on a fragment of golden path. */
 {
 struct sqlConnection *conn = hAllocConn(database);
 struct sqlConnection *conn2 = hAllocConn(database);
 struct sqlConnection *conn3 = hAllocConn(database);
 char query[256];
 struct sqlResult *sr;
 char **row;
 char query2[256];
 struct sqlResult *sr2;
 char **row2;
@@ -22348,30 +22423,58 @@
 
 wordCount = chopLine(dupe, words);
 if (wordCount > 0)
     {
     num = 0;
     if (wordCount > 1)
 	num = atoi(words[1]);
     if (num < 3) num = 3;
     footPrinterSampleClick(conn, tdb, item, start, num);
     }
 printTrackHtml(tdb);
 freez(&dupe);
 hFreeConn(&conn);
 }
 
+void bigPslHandlingCtAndGeneric(struct sqlConnection *conn, struct trackDb *tdb,
+                     char *item, int start, int end)
+/* Special option to show all alignments for blat ct psl */
+{
+
+if (startsWith("ct_blat", tdb->track) && !sameString(item,"PrintAllSequences"))
+    printf("<A href id='genericPslShowAllLink'>Show All</A>\n");
+
+printf("<div id=genericPslShowItem style='display: block'>\n");
+genericBigPslClick(NULL, tdb, item, start, end);
+printf("</div>\n");
+
+if (startsWith("ct_blat", tdb->track) && !sameString(item,"PrintAllSequences"))
+    {
+    printf("<div id=genericPslShowAll style='display: none'>\n");
+    genericBigPslClick(NULL, tdb, "PrintAllSequences", start, end);
+
+    printf("</div>\n");
+
+    jsInline("$('#genericPslShowAllLink').click(function(){\n"
+	    "  $('#genericPslShowAll')[0].style.display = 'block';\n"
+	    "  $('#genericPslShowItem')[0].style.display = 'none';\n"
+	    "  $('#genericPslShowAllLink')[0].style.display = 'none';\n"
+	    "return false;\n"
+	    "});\n");
+    }
+}
+
 void hgCustom(char *trackId, char *fileItem)
 /* Process click on custom track. */
 {
 char *fileName, *itemName;
 struct customTrack *ctList = getCtList();
 struct customTrack *ct;
 struct bed *bed = (struct bed *)NULL;
 int start = cartInt(cart, "o");
 int end = cartInt(cart, "t");
 char *item = cartString(cart, "i");
 char *type;
 fileName = nextWord(&fileItem);
 for (ct = ctList; ct != NULL; ct = ct->next)
     if (sameString(trackId, ct->tdb->track))
 	break;
@@ -22382,31 +22485,31 @@
 itemName = skipLeadingSpaces(fileItem);
 printf("<H2>%s</H2>\n", ct->tdb->longLabel);
 if (sameWord(type, "array"))
     doExpRatio(ct->tdb, fileItem, ct);
 else if ( startsWith( "longTabix", type))
     doLongTabix(ct->tdb, item);
 else if (sameWord(type, "encodePeak"))
     doEncodePeak(ct->tdb, ct, fileName);
 else if (sameWord(type, "bigNarrowPeak"))
     doBigEncodePeak(ct->tdb, NULL, item);
 else if (sameWord(type, "bigWig"))
     bigWigCustomClick(ct->tdb);
 else if (sameWord(type, "bigChain"))
     genericChainClick(NULL, ct->tdb, item, start, "seq");
 else if (sameWord(type, "bigPsl"))
-    genericBigPslClick(NULL, ct->tdb, item, start, end);
+     bigPslHandlingCtAndGeneric(NULL, ct->tdb, item, start, end);
 else if (sameWord(type, "bigMaf"))
     genericMafClick(NULL, ct->tdb, item, start);
 else if (sameWord(type, "bigDbSnp"))
     doBigDbSnp(ct->tdb, item);
 else if (sameWord(type, "bigBed") || sameWord(type, "bigGenePred") || sameWord(type, "bigLolly"))
     bigBedCustomClick(ct->tdb);
 else if (startsWith("bigRmsk", type))
     doBigRmskRepeat(ct->tdb, item);
 else if (sameWord(type, "bigBarChart") || sameWord(type, "barChart"))
     doBarChartDetails(ct->tdb, item);
 else if (sameWord(type, "bigInteract") || sameWord(type, "interact"))
     doInteractDetails(ct->tdb, item);
 else if (sameWord(type, "bam") || sameWord(type, "cram"))
     doBamDetails(ct->tdb, itemName);
 else if (sameWord(type, "vcfTabix") || sameWord(type, "vcfPhasedTrio"))