a1489c0fc1c99793e499e3915bc346b581664ad4 max Wed Jul 8 02:37:20 2026 -0700 Add support for all NCBI alternative genetic codes to dnautil Adds struct geneticCode plus the full set of NCBI translation tables (from gc.prt) so DNA can be translated with any genetic code, not just the Standard and Vertebrate Mitochondrial codes that were hardcoded. New API: geneticCodeForId/geneticCodeForName, lookupCodonInCode, isStopCodonInCode, dnaTranslateSomeInCode (explicit-handle, reentrant), and setDefaultGeneticCode for the process-global default. lookupCodon and friends are unchanged in behavior, still defaulting to the Standard code. The genetic code data lives in the auto-generated lib/geneticCodeTable.h, produced by oneShot/dnaGeneticCodes/dnaGeneticCodes.py from NCBI's gc.prt. Added a unit test under lib/tests. refs #16550 diff --git src/inc/dnautil.h src/inc/dnautil.h index 68ae2544455..f7d8d63e421 100644 --- src/inc/dnautil.h +++ src/inc/dnautil.h @@ -96,66 +96,103 @@ enum dnaCase {dnaUpper,dnaLower,dnaMixed,}; /* DNA upper, lower, or mixed case? */ /* Convert U's to T's */ void toDna(DNA *dna); /* Convert T's to U's */ void toRna(DNA *dna); int cmpDnaStrings(DNA *a, DNA *b); /* Compare using screwy non-alphabetical DNA order TCGA */ typedef char Codon; /* Our codon type. */ +struct geneticCode +/* One NCBI genetic code / translation table, e.g. Standard or Vertebrate + * Mitochondrial. The aa/starts data for all codes is auto-generated from + * NCBI's gc.prt; both strings are 64 chars indexed in the internal codon + * order (base1 outer, base3 inner, each t,c,a,g). */ + { + int id; /* NCBI transl_table id, e.g. 1, 2, 11. */ + char *name; /* Descriptive name, e.g. "Vertebrate Mitochondrial". */ + char *aa; /* 64 amino acids in codon order, '*' = stop. */ + char *starts; /* 64 start flags in codon order, 'M' = start. */ + }; + +struct geneticCode *geneticCodeForId(int id); +/* Return the genetic code with the given NCBI transl_table id (1 = Standard, + * 2 = Vertebrate Mitochondrial, 11 = Bacterial, ...), or NULL if none. */ + +struct geneticCode *geneticCodeForName(char *name); +/* Return the genetic code with the given name (case-insensitive), or NULL. */ + +void setDefaultGeneticCode(int id); +/* Set the genetic code used by lookupCodon/isStopCodon/dnaTranslateSome to the + * NCBI transl_table with the given id (1 = Standard). Aborts on unknown id. + * Sets process-global state; not thread-safe. */ + +AA lookupCodonInCode(struct geneticCode *code, DNA *dna); +/* Return single letter code (upper case) for protein using the given genetic + * code. Returns X for bad input, 0 for stop codon. */ + /* Return single letter code (upper case) for protein. * Returns X for bad input, 0 for stop codon. - * The "Standard" Code */ + * Uses the default genetic code (Standard unless setDefaultGeneticCode + * changed it). */ AA lookupCodon(DNA *dna); AA lookupUniqCodon(DNA *dna); +boolean isStopCodonInCode(struct geneticCode *code, DNA *dna); +/* Return TRUE if it's a stop codon in the given genetic code. */ + boolean isStopCodon(DNA *dna); /* Return TRUE if it's a stop codon. */ boolean isKozak(char *dna, int dnaSize, int pos); /* Return TRUE if it's a Kozak compatible start, using a relatively * weak definition (either A/G 3 bases before or G after) . */ boolean isReallyStopCodon(char *dna, boolean selenocysteine); /* Return TRUE if it's really a stop codon, even considering * possibilility of selenocysteine. */ /* Returns one letter code for protein, * 0 for stop codon or X for bad input, * Vertebrate Mitochondrial Code */ AA lookupMitoCodon(DNA *dna); Codon codonVal(DNA *start); /* Return value from 0-63 of codon starting at start. * Returns -1 if not a codon. */ DNA *valToCodon(int val); /* Return codon corresponding to val (0-63) */ extern char *aaAbbr(int i); /* return pointer to AA abbrevation */ extern char aaLetter(int i); /* return AA letter */ +void dnaTranslateSomeInCode(struct geneticCode *code, DNA *dna, char *out, int outSize); +/* Translate DNA with the given genetic code upto a stop codon or until + * outSize-1 amino acids, whichever comes first. Output will be zero + * terminated. */ + void dnaTranslateSome(DNA *dna, char *out, int outSize); /* Translate DNA upto a stop codon or until outSize-1 amino acids, * whichever comes first. Output will be zero terminated. */ char *skipIgnoringDash(char *a, int size, bool skipTrailingDash); /* Count size number of characters, and any * dash characters. */ int countNonDash(char *a, int size); /* Count number of non-dash characters. */ int nextPowerOfFour(long x); /* Return next power of four that would be greater or equal to x. * For instance if x < 4, return 1, if x < 16 return 2.... * (From biological point of view how many bases are needed to