Skip to main content

A lightweight, dependency-free biological sequence processing toolkit (FASTA/FASTQ, stats, k-mer, minimizer, indexing).

Project description

bioseqkit

CI Docs PyPI Python License: MIT

A lightweight, dependency-free biological sequence processing toolkit built from scratch in pure Python. bioseqkit implements FASTA/FASTQ parsing, sequence statistics, transformations, k-mer / minimizer analysis and FAI-like random-access indexing, exposed both as a Python API and a command-line tool.

The project is a teaching implementation for BIO2502 (Programming Languages for Biological Computing): it deliberately re-implements the low-level I/O, streaming and indexing logic instead of relying on Biopython, so the core design patterns of bioinformatics data handling are made explicit.

Features

  • Streaming FASTA/FASTQ parsers (io) — generator based, constant memory, transparent gzip support, Phred quality decoding.
  • Statistics (stats) — length distribution, N50, GC content, N-base ratio, base-composition matrix.
  • Transformations (transform) — reverse complement (IUPAC aware), DNA↔RNA transcription, and six-frame translation with the standard genetic code.
  • k-mer analysis (kmer) — counting, top-k, canonical k-mers, multi-process parallel counting, and minimizer sampling.
  • FAI-like indexing (index) — samtools faidx-compatible index for chr:start-end random access without scanning the whole file.
  • CLI (cli) — stats, revcomp, translate, transcribe, kmer, minimizer, index, fetch.
  • NCBI download (entrez) — fetch reference sequences via E-utilities (standard-library HTTP only).

Project layout

bioseqkit/
├── pyproject.toml          # src-layout, PEP 621 metadata, console script
├── README.md
├── LICENSE
├── src/bioseqkit/
│   ├── __init__.py         # public API
│   ├── io.py               # FASTA/FASTQ parsers
│   ├── stats.py            # sequence statistics
│   ├── transform.py        # revcomp + six-frame translation
│   ├── kmer.py             # k-mer / minimizer (serial + parallel)
│   ├── index.py            # FAI-like random-access index
│   ├── entrez.py           # NCBI download helper
│   └── cli.py              # argparse CLI
├── tests/                  # pytest suite (io/stats/transform/kmer/index/cli)
├── benchmarks/             # benchmark driver + complexity analysis
├── workflow/               # Snakemake pipeline (Snakefile)
├── config/config.yaml      # workflow configuration
├── examples/
│   ├── demo.ipynb          # Jupyter demo (stats, GC, k-mer spectrum, ...)
│   └── example_data/sample.fa
├── docs/                   # Sphinx documentation
├── flake.nix               # Nix flake: reproducible dev shell + Docker/Apptainer images
├── flake.lock              # pinned nixpkgs revision (bit-reproducible builds)
└── .github/workflows/ci.yml

Installation

Requires Python >= 3.10. The core package has no runtime dependencies.

pip install bioseqkit

# with optional extras (plots for the notebook / NCBI download / docs)
pip install "bioseqkit[viz,net,docs]"

Reproducible builds with Nix

A Nix flake is provided as a single, bit-for-bit reproducible source of truth. Because flake.lock pins the exact nixpkgs revision, every build — the package, the dev shell and the container images — is fully reproducible. From the one flake you can:

nix run   .                 # run the bioseqkit CLI
nix build .#default         # build the Python package (runs the test suite)
nix develop                 # enter a reproducible dev shell (python + uv + typst + pytest ...)

nix build .#docker          # build an OCI/Docker image  -> docker load < result
nix build .#apptainer       # build an Apptainer/Singularity (.sif) image

This supersedes a hand-written Dockerfile/Apptainer recipe: both container images are derived from the same pinned dependency graph, so they can never drift from the tested build.

Command-line usage

bioseqkit stats    examples/example_data/sample.fa      # JSON statistics
bioseqkit revcomp  examples/example_data/sample.fa      # reverse complement
bioseqkit translate examples/example_data/sample.fa     # six-frame translation
bioseqkit transcribe examples/example_data/sample.fa    # DNA -> RNA (T -> U)
bioseqkit kmer     examples/example_data/sample.fa -k 5 --top 10 --canonical
bioseqkit kmer     examples/example_data/sample.fa -k 5 -t 4   # parallel
bioseqkit minimizer examples/example_data/sample.fa -k 15 -w 10
bioseqkit index    examples/example_data/sample.fa      # write *.fai
bioseqkit fetch    examples/example_data/sample.fa seq2:1-16

Understanding the output

stats prints a JSON object; each field means:

Field Meaning
n_seqs number of sequences in the file
total_length sum of all sequence lengths (bp)
min_length / max_length shortest / longest sequence
mean_length average sequence length
n50 length such that sequences ≥ this length cover ≥ 50% of total_length (assembly contiguity metric)
gc_content fraction of G/C bases in [0, 1] — useful for species/GC-bias assessment
n_ratio fraction of ambiguous N bases — a data-quality indicator
base_counts per-base counts (A/C/G/T/N/...), the base-composition matrix

kmer prints a tab-separated kmer<TAB>count table, one line per k-mer, sorted by descending frequency (top---top). With --canonical, a k-mer and its reverse complement are counted together, so results are strand-independent.

revcomp / translate / transcribe emit FASTA to stdout. translate produces six records per input sequence, suffixed _frame+1..+3 (forward strand, offsets 0/1/2) and _frame-1..-3 (reverse-complement strand); * denotes a stop codon and X an untranslatable codon. transcribe returns the RNA form of each sequence (every T replaced by U).

minimizer prints seq_id<TAB>position<TAB>minimizer — the sampled k-mers and their 0-based positions along the sequence.

index writes a <file>.fai (name, length, offset, bases-per-line, bytes-per-line); fetch prints the requested sub-sequence as FASTA using 1-based inclusive coordinates.

Reproducible pipeline (Snakemake)

A Snakemake workflow chains the CLI into a "data acquisition → processing → analysis" pipeline (fetch_input → stats + kmer + index):

snakemake -c1                                   # run offline on the bundled example
snakemake -n                                    # dry run: show the job DAG
snakemake -c4 --config accession=NC_012920.1 k=6  # download human chrM from NCBI, then analyse

Outputs are written to results/ (stats.json, kmers.tsv, input.fa.fai). Configure input, accession and parameters in config/config.yaml.

Benchmarks & complexity

python benchmarks/bench.py            # sweep 100 kbp .. 4 Mbp, write results.csv + scalability.png

See benchmarks/README.md for the full time/space complexity table and measured scaling. In short: k-mer counting is O(n·k) and scales to ~3× on four workers for inputs ≥ 1 Mbp; the FAI index builds in O(n) and answers random fetch queries in tens of microseconds, independent of file size. Micro-benchmarks are also runnable via pytest tests/test_benchmark.py --benchmark-only.

Python API

import bioseqkit as bsk

for rec in bsk.parse_fasta("examples/example_data/sample.fa"):
    print(rec.id, len(rec), bsk.gc_content(rec.sequence))

print(bsk.reverse_complement("ATGC"))            # -> GCAT
print(bsk.transcribe("ATGC"))                    # -> AUGC
print(bsk.translate("ATGGCCTAA"))                # -> MA*

counts = bsk.count_kmers("ACGTACGTACGT", k=3, canonical=True)
print(bsk.top_kmers(counts, 3))

idx = bsk.build_faidx("examples/example_data/sample.fa")
print(idx.fetch("seq2", 1, 16))

Testing

uv run --with pytest pytest -q      # 39 tests

Continuous integration (GitHub Actions) runs ruff linting, the pytest suite with coverage on Python 3.10–3.12 for every push, and builds & deploys the Sphinx documentation to GitHub Pages.

Data sources

For teaching and quick tests, a small bacterial genome or the human mitochondrion (chrM, ~16.5 kbp) is recommended to keep files small. The bundled examples/example_data/sample.fa is a tiny synthetic sequence for offline testing; demo.ipynb downloads real data from NCBI when a network connection is available and falls back to the bundled file otherwise.

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

bioseqkit-0.2.0.tar.gz (257.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

bioseqkit-0.2.0-py3-none-any.whl (18.3 kB view details)

Uploaded Python 3

File details

Details for the file bioseqkit-0.2.0.tar.gz.

File metadata

  • Download URL: bioseqkit-0.2.0.tar.gz
  • Upload date:
  • Size: 257.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Arch Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for bioseqkit-0.2.0.tar.gz
Algorithm Hash digest
SHA256 36a06cdbb5e5a910691bd8ff82382d051a12d263f51b33f86a85b5016f17e582
MD5 3dab8d31b8cf41ed81f4601475c40344
BLAKE2b-256 0417736266f7006139ba37a5809261a808ae58db48cd145b8a610d2d342fe8b2

See more details on using hashes here.

File details

Details for the file bioseqkit-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: bioseqkit-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 18.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Arch Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for bioseqkit-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 28379a3b5a72d969a6abd9d3f42c8952a6ea7b94f9661931186d02aa756377de
MD5 7cc0c5d7c9405d3ab95ee21ec1ae6abb
BLAKE2b-256 778b5f0b9a3e7bf26ff4eb32320a8f18662f3a0c47c82c7ac1c3bfef004edf71

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page