codonyat · viral NGS variant calling

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 viral amplicon sequencing.

GitHub repository · PyPI

Highlights

Installation

pip install codonyat

Requires Python 3.10 or newer; the only runtime dependency is Biopython.

This project is the Python package only. 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

Install the package and run the variant caller directly on a SAM file:

codonyat sample.sam reference.fasta amplicons.tsv \
    --protein RT \
    --ratio-upper 3.16 \
    --entropy-threshold 0.5

Output: sample.sam.tsv (columns: FILE, REFERENCE, PROTEIN, VARIANT, POSITION, FREQ, FWCOV, RVCOV, TOTALCOV, RATIO) and sample.sam.xml with per-position depth and variant elements.

The lightweight codonyat-runner entry point supports --csv-path / --xml-path overrides for custom output locations:

codonyat-runner sample.sam reference.fasta amplicons.tsv \
    --protein RT --ratio-upper 3.1 --csv-path results.tsv

Reference FASTA format

The FASTA header must include protein annotations in Name(Description):start-end format, separated by semicolons:

>K03455|HIVHXB2CG PR(Protease):2253-2549;RT(Reverse Transcriptase):2550-3869;INT(Integrase):4230-5093
TGGAAGGGCTAATTCACTCCCAACGAAGAC...

Coordinates are 1-based positions on the reference sequence. The --protein flag selects which annotation to use for variant calling.

Package API

Import the core objects for tighter integration:

from aa_caller import SamContainer, FullReference, parse_amplicons

Use call_variants to run variant calling from Python:

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())

Adapt an argparse.Namespace or mapping with call_variants_from_args:

from argparse import Namespace
from aa_caller import call_variants_from_args

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)

Development

Install with dev tooling to match CI:

pip install --upgrade pip
pip install -e .[dev]

Run the checks that execute in CI:

ruff check .
python -m pytest
python -m build && twine check dist/*

Project structure

codonyat/
├── aa_caller/            # Python package
│   ├── cli.py            # CLI entry point
│   ├── runner.py         # Python API (call_variants)
│   ├── container.py      # SamContainer — variant aggregation
│   ├── sam.py            # SamEntry — CIGAR-aware SAM parsing
│   ├── reference.py      # FullReference — FASTA + annotations
│   ├── models.py         # Protein, Amplicon, Variant, Qual
│   ├── validators.py     # Input file validation
│   ├── genetic_code.py   # Codon translation table
│   └── constants.py      # Default thresholds
├── tests/                # pytest suite (unit + integration)
├── docs/index.html       # This page
└── pyproject.toml        # Python package metadata