4aa77873cb618e254b2f90d091d7bdef844947c2 max Wed Jul 8 04:28:42 2026 -0700 Let assembly hubs assign genetic codes per sequence for amino acid display Adds a "codonTable" genomes.txt setting, e.g. "codonTable default=1 NC_017929.1=13", so an assembly hub can pick the NCBI translation table used to show amino acids for each sequence. New hGeneticCodeForChrom(db, chrom) in hdb.c resolves the code (per-db cached), falling back to the previous behavior: chrM/chrMT use the vertebrate mitochondrial code, everything else the standard code. Wired into the two browser display paths, which both go through cds.c's baseColorLookupCodon: the base position track three-frame translation and codon-colored annotation tracks such as gene predictions (also PSL/BAM). Also used for the hgc SNP amino acid details, and genePredTranslate gains a db parameter (genePredToProt gains an optional -db flag) so command-line translation can honor the same setting. Documented in assemblyHubHelp.html. refs #16550 diff --git src/hg/hgc/hgc.c src/hg/hgc/hgc.c index 5c0bfcd230a..e453aff4613 100644 --- src/hg/hgc/hgc.c +++ src/hg/hgc/hgc.c @@ -19289,34 +19289,31 @@ int snpCodonPos = geneIsRc ? (2 - ((exonEnd - snpEnd) + exonFrame) % 3) : (((snpStart - exonStart) + exonFrame) % 3); refCodon[0] = getSnpTxBase(gene, exonIx, snpStart, -snpCodonPos); refCodon[1] = getSnpTxBase(gene, exonIx, snpStart, 1 - snpCodonPos); refCodon[2] = getSnpTxBase(gene, exonIx, snpStart, 2 - snpCodonPos); refCodon[3] = '\0'; if (geneIsRc) { reverseComplement(refCodon, strlen(refCodon)); snpCodonPos = 2 - snpCodonPos; } if (pSnpCodonPos != NULL) *pSnpCodonPos = snpCodonPos; if (pRefAA != NULL) { - if (isMito(seqName)) - *pRefAA = lookupMitoCodon(refCodon); - else - *pRefAA = lookupCodon(refCodon); + *pRefAA = lookupCodonInCode(hGeneticCodeForChrom(database, seqName), refCodon); if (*pRefAA == '\0') *pRefAA = '*'; } } static char *highlightCodonBase(char *codon, int offset) /* If codon is a triplet and offset is 0 to 2, highlight the base at the offset. * Otherwise just return the given codon sequence unmodified. * Don't free the return value! */ { static struct dyString *dy = NULL; if (dy == NULL) dy = dyStringNew(0); dyStringClear(dy); if (strlen(codon) != 3) dyStringAppend(dy, codon); @@ -19369,35 +19366,31 @@ geneTrack, geneName, snpMisoLinkFromFunc("frameshift")); else if (diff > 0) printf(firstTwoColumnsPctS "%s (insertion of %d codon%s)\n", geneTrack, geneName, snpMisoLinkFromFunc("inframe_insertion"), (int)(diff/3), (diff > 3) ? "s" : ""); else printf(firstTwoColumnsPctS "%s (deletion of %d codon%s)\n", geneTrack, geneName, snpMisoLinkFromFunc("inframe_deletion"), (int)(-diff/3), (diff < -3) ? "s" : ""); } else if (alSize == 1 && refIsSingleBase) { char snpCodon[4]; safecpy(snpCodon, sizeof(snpCodon), refCodon); snpCodon[snpCodonPos] = alBase; - char snpAA = '\0'; - if (isMito(seqName)) - snpAA = lookupMitoCodon(snpCodon); - else - snpAA = lookupCodon(snpCodon); + char snpAA = lookupCodonInCode(hGeneticCodeForChrom(database, seqName), snpCodon); if (snpAA == '\0') snpAA = '*'; char refCodonHtml[16], snpCodonHtml[16]; safecpy(refCodonHtml, sizeof(refCodonHtml), highlightCodonBase(refCodon, snpCodonPos)); safecpy(snpCodonHtml, sizeof(snpCodonHtml), highlightCodonBase(snpCodon, snpCodonPos)); if (refAA != snpAA) { if (refAA == '*') printf(firstTwoColumnsPctS "%s %c (%s) --> %c (%s)\n", geneTrack, geneName, snpMisoLinkFromFunc("stop-loss"), refAA, refCodonHtml, snpAA, snpCodonHtml); else if (snpAA == '*') printf(firstTwoColumnsPctS "%s %c (%s) --> %c (%s)\n", geneTrack, geneName, snpMisoLinkFromFunc("nonsense"), refAA, refCodonHtml, snpAA, snpCodonHtml); else