b5a4ddd8543a87f46988a60069148b0f2e1a8031 max Mon Aug 10 08:37:29 2026 -0700 hgBlat/hgPcr: show the chrUn info note (fix swapped startsWith args), refs #37893 The chrUn branch of the sequence-type note used startsWith(name, "chrUn"), but startsWith(start, string) tests whether string begins with start, so it asked whether "chrUn" begins with the sequence name and never matched. As a result chrUn (unplaced) sequences got no info icon on the new BLAT results page, and no note on the classic results page or in hgPcr, while _alt/_fix/ _random (which use endsWith) worked. Fix the argument order in all three. Also, on the new results page, check the sequence's aliases and not just its single display name, so a hit whose displayed label is an accession but which has a chrUn/alt/fix alias (e.g. a GenArk hub) still gets the note. diff --git src/hg/hgBlat/hgBlat.c src/hg/hgBlat/hgBlat.c index 5235a06b1c0..3f71514befe 100644 --- src/hg/hgBlat/hgBlat.c +++ src/hg/hgBlat/hgBlat.c @@ -523,35 +523,52 @@ hgcUrl, psl->tStart, pslName, cgiEncode(faName), psl->qName, psl->tName, psl->tStart, psl->tEnd, database, uiState); printf("details "); } static char *chromTypeNote(char *tName) /* Return a short explanation for special sequence names (alt/fix/random/hap/unplaced), or NULL for a * normal chromosome. tName should be the display name the user sees. */ { if (endsWith(tName, "_fix")) return "Assembly fix patch: corrects an error in the reference assembly."; if (endsWith(tName, "_alt") || stringIn("_hap", tName)) return "Alternate haplotype: an alternate sequence for this region."; if (endsWith(tName, "_random")) return "Unlocalized sequence: known chromosome, position not determined."; -if (startsWith(tName, "chrUn")) +if (startsWith("chrUn", tName)) return "Unplaced sequence: chromosome of origin unknown."; return NULL; } +static char *blatSeqNote(char *tName, char *displayName) +/* The info-icon note for one hit. chromTypeNote() only sees the single display name, but a + * sequence can have several aliases and the chosen display name may not be the chrUn/alt/fix one + * (e.g. a GenArk hub shows a GenBank accession while "chrUn_..." is only an alias). So if the + * display name looks ordinary, scan the sequence's other aliases too. */ +{ +char *note = chromTypeNote(displayName); +if (note == NULL) + { + struct slName *al; /* chromAliasFindAliases returns a cached list - do not free it */ + for (al = chromAliasFindAliases(tName); al != NULL; al = al->next) + if ((note = chromTypeNote(al->name)) != NULL) + break; + } +return note; +} + static char *blatBrowserUrl(struct psl *psl, char *database, char *browserUrl, char *pslName, char *faName, char *customText, char *uiState, char *unhideTrack, boolean withUiState) /* Return a Genome Browser URL for one BLAT hit. withUiState appends the hgsid; it is included on * the in-tab link but omitted from the new-tab link, matching the classic hyperlink behavior. */ { struct dyString *dy = dyStringNew(256); dyStringPrintf(dy, "%s?position=%s:%d-%d&db=%s", browserUrl, psl->tName, psl->tStart + 1, psl->tEnd, database); if (customText) dyStringPrintf(dy, "&hgt.customText=%s", customText); else if (!autoBigPsl && pslName != NULL) dyStringPrintf(dy, "&ss=%s+%s", pslName, faName); if (withUiState) dyStringPrintf(dy, "&%s", uiState); dyStringPrintf(dy, "%s", unhideTrack); return dyStringCannibalize(&dy); @@ -696,31 +713,31 @@ { ++rank; double ident = 100.0 - pslCalcMilliBad(psl, TRUE) * 0.1; char *displayChromName = chromAliasGetDisplayChrom(database, cart, psl->tName); char *inTabUrl = blatBrowserUrl(psl, database, browserUrl, pslName, faName, customText, uiState, unhideTrack, TRUE); char *newTabUrl = blatBrowserUrl(psl, database, browserUrl, pslName, faName, customText, uiState, unhideTrack, FALSE); jsonWriteObjectStart(jw, NULL); jsonWriteNumber(jw, "rank", rank); jsonWriteString(jw, "qName", psl->qName); jsonWriteNumber(jw, "score", pslScore(psl)); jsonWriteDouble(jw, "identity", ident); jsonWriteString(jw, "chrom", displayChromName); - char *note = chromTypeNote(displayChromName); /* note must match the NAME the user sees */ + char *note = blatSeqNote(psl->tName, displayChromName); /* check the display name and its aliases */ if (note != NULL) jsonWriteString(jw, "chromNote", note); jsonWriteString(jw, "strand", psl->strand); jsonWriteNumber(jw, "tStart", psl->tStart + 1); jsonWriteNumber(jw, "tEnd", psl->tEnd); jsonWriteNumber(jw, "span", psl->tEnd - psl->tStart); jsonWriteNumber(jw, "qStart", psl->qStart + 1); jsonWriteNumber(jw, "qEnd", psl->qEnd); jsonWriteNumber(jw, "qSize", psl->qSize); jsonWriteNumber(jw, "matches", psl->match + psl->repMatch); jsonWriteNumber(jw, "misMatch", psl->misMatch); jsonWriteNumber(jw, "gaps", psl->qNumInsert + psl->tNumInsert); jsonWriteNumber(jw, "blocks", psl->blockCount); jsonWriteString(jw, "browserUrl", inTabUrl); jsonWriteString(jw, "newTabUrl", newTabUrl); @@ -1188,31 +1205,31 @@ char *displayChromName = chromAliasGetDisplayChrom(database, cart, psl->tName); printf("%s",displayChromName); spaceOut(stdout, maxTChromNameSize - strlen(displayChromName)); printf(" %-2s %9d %9d %6d", psl->strand, psl->tStart+1, psl->tEnd, psl->tEnd - psl->tStart); // if you modify this, also modify hgPcr.c:doQuery, which implements a similar feature char *seq = psl->tName; if (endsWith(seq, "_fix")) printf(" What is chrom_fix?"); else if (endsWith(seq, "_alt")) printf(" What is chrom_alt?"); else if (endsWith(seq, "_random")) printf(" What is chrom_random?"); - else if (startsWith(seq, "chrUn")) + else if (startsWith("chrUn", seq)) printf(" What is a chrUn sequence?"); printf("\n"); } printf("\n"); webNewSection("Help"); puts("

Missing a match?
"); puts("What is chr_alt & chr_fix?

\n"); puts("\n"); } } pslFreeList(&pslList); } void trimUniq(bioSeq *seqList)