c7fcdde6db52ba01fbabfa695b49205bf7261a33 max Tue Aug 4 07:40:32 2026 -0700 hgBlat/hgc: QA fixes for the new BLAT table view and alignment page Address Gerardo's QA findings on the new BLAT UI: - Table view: label each hit with its own query (new Query column + "Queries" count in the summary) when the search has multiple queries, reading cfg.multiQuery / hit.qName from the payload. - Table view: strip the "hub_NNN_" prefix from the Assembly field so hub assemblies no longer show a doubled prefix. - Alignment page: strip the same prefix from the organism in the page title for non-GenArk assembly hubs (blatAsmLabel fallback path). - Table view: do not pre-select hit #1; show a prompt until the user clicks a row, since top hits are often tied. - Table view: add a divider between the Browser / New tab / Alignment links. - Alignment page: sidebar link now reads "Side by Side Alignment" to match the section heading. - Alignment page: comma-format coordinates and base counts in the summary, matching the table view and the rest of the browser. refs #37893 diff --git src/hg/hgc/hgc.c src/hg/hgc/hgc.c index 8ea4709b154..e8ae42ba93d 100644 --- src/hg/hgc/hgc.c +++ src/hg/hgc/hgc.c @@ -9014,31 +9014,34 @@ htmlFramesetStart(title); /*showSomeAlignment(psl, qSeq, gftDnaX, psl->qStart, psl->qEnd, name, 0, 0); */ showSomeAlignment(psl, qSeq, gftDnaX, psl->qStart, psl->qEnd, name, cdsStart, cdsEnd); } static char *blatAsmLabel(char *database) /* A user-facing assembly label for the page title. For an assembly hub the internal * "hub_NNN_GCA_..." database name is not helpful, so use the assembly's friendly organism plus its * accession; for a native assembly just use the db name (e.g. "hg38"). */ { if (!trackHubDatabase(database)) return cloneString(database); char *acc = trackHubSkipHubName(database); /* drop the "hub_NNN_" prefix -> the accession */ char *org = hGenome(acc); /* GenArk table's friendly genome name for GC* accs */ if (isEmpty(org)) + { org = trackHubAssemblyField(database, "organism"); /* else the hub's genomes.txt organism */ + org = trackHubSkipHubName(org); /* strip the "hub_NNN_" prefix addHubName() baked in */ + } if (isEmpty(org)) return cloneString(acc); char buf[256]; safef(buf, sizeof buf, "%s %s", org, acc); return cloneString(buf); } static void showSomeAlignmentModern(struct psl *psl, bioSeq *oSeq, enum gfType qType, int qStart, int qEnd, char *qName, int cdsS, int cdsE) /* Modern single-page version of showSomeAlignment for hgBlat's new table mode: a gold title bar with * Back/Share buttons, a full-height "jump to" sidebar, then an "Alignment Summary" and the base-by- * base alignment inlined below with steel-blue section headers, so the whole page scrolls (no * ). The alignment body itself is generated by the shared library as before. The caller * supplies the page chrome via webStartGbNoBanner()/webEndGb() - a menubar and
with no legacy * section tables - so everything here is plain, table-free HTML. */ @@ -9122,53 +9125,60 @@ printf("BLAT Base Alignment: %s", blatAsmLabel(database)); printf(""); printf("" "\xe2\x80\xb9 Back to results", cartSessionId(cart)); if (canShare) printf("Share a link"); printf("\n"); /* one white panel laid out as two grid columns: a full-height "jump to" sidebar on the left, and on * the right an "Alignment Summary" header, the summary line, and the base-by-base alignment inlined * so the whole page scrolls */ printf("
\n"); printf("
\n"); printf("

Alignment Summary

\n"); -printf("

%s aligned to %s:%d-%d, " +/* comma-format the coordinates and base counts, matching the new Table view (readable at the + * hundreds-of-millions scale of genomic coordinates, and the convention elsewhere in the browser) */ +char tStartC[32], tEndC[32], matchC[32], qSizeC[32]; +sprintLongWithCommas(tStartC, psl->tStart + 1); +sprintLongWithCommas(tEndC, psl->tEnd); +sprintLongWithCommas(matchC, psl->match + psl->repMatch); +sprintLongWithCommas(qSizeC, psl->qSize); +printf("

%s aligned to %s:%s-%s, " "%.1f%% identity, " - "%d of %d bases matched, strand %s.

\n", - qName, chrom, psl->tStart + 1, psl->tEnd, idColor, ident, - psl->match + psl->repMatch, psl->qSize, psl->strand); + "%s of %s bases matched, strand %s.

\n", + qName, chrom, tStartC, tEndC, idColor, ident, + matchC, qSizeC, psl->strand); if (isNotEmpty(aliasStr)) printf("

Genome sequence %s is also known as: %s.

\n", chrom, aliasStr); /* The shared library returns the number of alignment blocks it actually shows. The DNA path merges * blocks separated by gaps <= 8 bases, so this can be fewer than psl->blockCount; use it (not * psl->blockCount) so the sidebar's "Block N" links match the #1..#N anchors that were emitted. */ int blockCount; if (qType == gftRna || qType == gftDna) blockCount = showPartialDnaAlignment(psl, oSeq, stdout, cdsS, cdsE, FALSE); else blockCount = showGfAlignment(psl, oSeq, stdout, qType, qStart, qEnd, qName); printf("
\n"); /* #blatAlnContent */ /* Sidebar, emitted after the alignment so blockCount is known; CSS grid puts it back in column 1. * The inner div is position:sticky so the links stay in view as the long alignment scrolls. */ printf("
\n"); printf("Only query sequence\n" "Only genome sequence\n" - "Side-by-side alignment\n"); + "Side by Side Alignment\n"); if (blockCount > 1) /* per-block jump links, indented under the side-by-side item */ { int bi; printf("
\n"); for (bi = 1; bi <= blockCount; ++bi) printf("Block %d\n", bi, bi); printf("
\n"); } printf("
\n"); printf("
\n"); /* #blatAlnBody */ /* The cDNA/Genomic section headers come from shared library code (fuzzyShow.c / pslShow.c) as * "cDNA " / "Genomic :"; relabel them to the sidebar wording via JS (there is no C * hook for it), keeping the #cDNA/#genomic jump anchors. qName and chrom are already sanitized. */