codonyat
codon-yat — A codon-aware amino acid variant typer from SAM alignments of viral NGS data.
A Python package for codon-level amino acid variant calling from SAM alignments of viral amplicon sequencing, including:
- SAM parsing that honors amplicon labels and strand orientation.
- CIGAR-aware codon extraction that correctly handles insertions, deletions, and soft clips.
- Ratio balancing, entropy tracking, and TSV/XML exporters mirroring the legacy Perl outputs.
- Configurable CLI flags for strand ratio bounds, entropy sensitivity, and target protein.
Highlights
- Produces consistent TSV/XML diagnostics while exposing Python objects (
SamContainer,FullReference, etc.) that downstream tooling can import. - Validates every input file before parsing to surface malformed SAM/FASTA/amplicon data early.
- Logs per-position entropy and strand balance for easier debugging in CI or local runs.
- Supports any protein target via
--protein(defaults to RT).
Installation
pip install codonyat
Requires Python 3.10 or newer. The only runtime dependency is Biopython.
Running it in a workflow
This repository contains only the Python package. To run codonyat on many samples (from FASTQ or SAM, with read QC, trimming, alignment and a merged report), use the separate Nextflow pipeline nf-codonyat, which installs this package from PyPI.
CLI usage
Once installed, the codonyat entry point is available:
codonyat sample.sam reference.fasta amplicons.tsv
Options
| Flag | Default | Description |
|---|---|---|
--protein |
RT |
Protein(s) to analyse: one name, a comma-separated list (e.g. PR,RT,INT, counted in a single pass) or all (every protein annotated in the reference header). Names must match the FASTA header annotations |
--ratio-upper |
3.162 |
Upper bound for strand-ratio balancing |
--ratio-lower |
0.316 |
Lower bound for strand-ratio balancing |
--entropy-threshold |
0.0 |
Minimum Shannon entropy to mark a position as diverse |
Output
The CLI writes two files alongside the input SAM:
[sam-file].tsv— columns: FILE, REFERENCE, PROTEIN, VARIANT, POSITION, FREQ, FWCOV, RVCOV, TOTALCOV, RATIO[sam-file].xml— per-position<Depth>,<FwCover>,<RvCover>,<Variants>
With several proteins, the TSV has one header followed by each protein's rows (in the order requested), and the XML wraps each protein's positions in a <Protein name="..."> element. Single-protein output is unchanged.
Input and memory
The input can be SAM, gzip-compressed SAM (.sam.gz) or BAM (.bam; install the optional extra with pip install 'codonyat[bam]'). Records are streamed, so peak memory does not depend on the number of alignments: about 80–110 MB for 1 million alignments (see benchmarks/README.md).
Reference FASTA format
The reference FASTA header must include protein annotations in the format Name(Description):start-end, separated by semicolons:
>K03455|HIVHXB2CG PR(Protease):2253-2549;RT(Reverse Transcriptase):2550-3869;INT(Integrase):4230-5093
TGGAAGGGCTAATTCACTCCCAACGAAGAC...
Package API
Import aa_caller to reuse the core objects:
from aa_caller import SamContainer, FullReference, parse_amplicons
Python wrapper
Use call_variants to run variant calling from Python without touching the CLI:
from pathlib import Path
from aa_caller import call_variants
result = call_variants(
sam_path=Path("reads.sam"),
reference_path=Path("reference.fasta"),
amplicons_path=Path("amps.tsv"),
protein="RT",
ratio_upper=3.2,
)
print(result.csv_path, result.xml_path)
print(result.container.variants.keys())
If you already have an argparse.Namespace or mapping of the CLI arguments, call_variants_from_args adapts them directly:
from argparse import Namespace
args = Namespace(
sam_file="reads.sam",
reference_file="reference.fasta",
amplicons_file="amps.tsv",
protein="RT",
ratio_upper=3.2,
)
call_variants_from_args(args)
CLI wrapper
A lightweight runner at codonyat-runner exposes the same arguments as call_variants_from_args:
codonyat-runner reads.sam reference.fasta amps.tsv --protein RT --ratio-upper 3.1 --csv-path results.tsv
Development
Install the repository with the optional dev tooling so your local environment matches CI:
pip install --upgrade pip
pip install -e .[dev]
Now you can run the same checks as .github/workflows/python-tests.yml:
ruff check .
python -m pytest
python -m build && twine check dist/*
Project structure
codonyat/
├── aa_caller/ # Python package
│ ├── cli.py # CLI entry point (codonyat)
│ ├── runner.py # Python API (call_variants, call_variants_from_args) and codonyat-runner
│ ├── container.py # SamContainer — variant aggregation engine
│ ├── sam.py # SamEntry — CIGAR-aware SAM record parser
│ ├── reference.py # FullReference — FASTA + protein annotation loader
│ ├── models.py # Protein, Amplicon, Variant, Qual dataclasses
│ ├── validators.py # Input file validation
│ ├── genetic_code.py # Codon translation table
│ └── constants.py # Default thresholds
├── tests/ # pytest suite (unit, integration, 1.0.3 regression fixtures)
├── benchmarks/ # synthetic SAM generator and memory benchmark notes (dev only)
├── CHANGELOG.md
├── docs/index.html # Project page (GitHub Pages)
└── pyproject.toml # Package metadata
Releasing
Publishing to PyPI is done by .github/workflows/publish-pypi.yml when a GitHub
release is published:
- Set
versioninpyproject.toml(e.g.1.0.3) and merge it tomain. - Create a tag
v<version>and a GitHub release from it. - The workflow builds the sdist and wheel, runs
twine check, checks that the tag matches the package version, and publishes via PyPI trusted publishing (GitHub environmentpypi).
License
MIT
Metadata
Release files for codonyat 1.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| codonyat-1.1.0.tar.gz | 28.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| codonyat-1.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 51.6 kB
Release files / codonyat-1.1.0.tar.gz
| Download URL | codonyat-1.1.0.tar.gz |
|---|---|
| Size | 28.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8da359e73222b964e87428a4652c2ae9ffb4b412d4a4430da358e6a0718c19c1
|
|
BLAKE2b-256 checksum How to use checksums |
cf6b92d01f74254e5dba8fc251b47cc88fb7af73dd13d243fe5acdc915a6fbed
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.5
|
Release files / codonyat-1.1.0-py3-none-any.whl
| Download URL | codonyat-1.1.0-py3-none-any.whl |
|---|---|
| Size | 23.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
36fc0e3bbaab380040702385e05b37b49e1224818590835a7d15941003f76ef7
|
|
BLAKE2b-256 checksum How to use checksums |
f1ea9734c2c6152fa50c65b6771c175d9e77dc4bc39941f2c3f4e43ab4a2c172
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.5
|