What is GFFBase?
A high-performance genomic-annotation engine — a SIMD Rust parser, a DuckDB
columnar backend and a zero-copy PyArrow interface — built for whole-genome
ingest and bulk machine-learning feature extraction, and a drop-in successor to
gffutils.
The legacy FeatureDB / Feature / create_db / DataIterator / GFFWriter /
merge_criteria API is preserved verbatim, so most scripts migrate by changing
one import line.
Install
pip install gffbase
Universal abi3 wheels: one binary per platform covers CPython 3.10 through
3.14, and no Rust toolchain is needed. Source and development builds are in the
installation guide.
0.3.0 is the current release — ingest 2.4–2.9× faster, in under a third of the memory on whole-genome files; loops over a live stream prefetched; and noisy files read as they were meant. Coming from 0.2.0, upgrade: 0.2.1 fixed defects that silently lost data. Coming from 0.1.0, 0.2 and later fix two SQL injection vulnerabilities (advisory) and have breaking changes. All are in the changelog.
Quick start
from gffbase import create_db
# Ingest a GTF or GFF3 — format auto-detected, gzip transparent.
with create_db("gencode.v49.basic.annotation.gtf.gz", "gencode.duckdb") as db:
# Walk one gene's hierarchy. GENCODE ids carry their version.
for tx in db.children("ENSG00000139618.19", level=1, featuretype="transcript"):
print(tx.id, tx.start, tx.end)
# Overlap query, routed to the per-seqid R-tree.
for exon in db.region("chr17:43044295-43125483", featuretype="exon"):
print(exon)
Coming from gffutils? import gffbase as gffutils is usually the only change
you need — but read the migration guide first,
for the one loop pattern you should not port unchanged.
Bulk extraction without Python objects
The workload GFFBase exists for: pull every exon for tens of thousands of
transcripts, hand the columns to a tensor, train. One set-based query returns
DuckDB's own Arrow buffers, and no Feature object is constructed at any
layer — where a per-feature Python loop allocates millions of throwaway
objects and that allocation dominates everything else.
exons = db.children_batched(
transcript_ids, # an iterable of 50 000 IDs
featuretype="exon",
format="arrow", # "df" and "polars" also supported
)
# A pyarrow.Table sharing memory with DuckDB. Its "anchor" column carries the
# input id for each row, so per-transcript groups survive without N queries.
import torch
starts = torch.from_numpy(exons.column("start").to_numpy())
region_batched() and parents_batched() offer the same zero-copy contract for
spatial and parent workloads. One trade to know: a loop over a gffbase iterator
(for g in db.features_of_type("gene"): db.children(g)) is prefetched and runs
within 1.4–3.5× of gffutils, but a loop over a list of ids of your own,
for i in ids: db.children(i), is slower — each call is a DuckDB statement
of its own — which is why the batched API exists.
End-to-end PyTorch and Hugging Face pipelines are in the ML workflows cookbook, and every method has a snippet in the usage gallery.
Measured against gffutils
Head-to-head across five canonical human-genome annotations — one run, one machine, one commit. gffbase ingests every corpus faster, 1.92× to 3.62×, into a database 0.61× to 0.89× the size of gffutils' SQLite file. The narrowest margin is the GENCODE GTF row, the arm least favourable to gffbase: with parent inference off, gffutils' GTF path is a plain bulk insert. Batched extraction, spatial indexing and SQL over the whole corpus come on top.
| Corpus | Format | Lines | gffbase ingest | legacy ingest | speedup | peak RSS (ingest + full validation) | spatial qps | batched (5 k anchors) |
|---|---|---|---|---|---|---|---|---|
| GENCODE v49 (basic) | GTF | 6,068,892 | 3 min 36 s | 6 min 54 s | 1.92× | 53.47 GB | 728 ±1% (n=5) | 614 ms / 1.93 M desc |
| GENCODE v49 (basic) | GFF3 | 6,066,054 | 3 min 13 s | 9 min 45 s | 3.03× | 61.93 GB | 770 ±1% (n=5) | 666 ms / 1.93 M desc |
| RefSeq GRCh38.p14 | GFF3 | 4,932,571 | 2 min 5 s | 6 min 31 s | 3.13× | 26.69 GB | 588 ±1% (n=5) | 443 ms / 999 k desc |
| CHESS 3.1.3 | GFF3 | 2,761,061 | 37.0 s | 2 min 14 s | 3.62× | 2.93 GB | 678 ±3% (n=5) | 155 ms / 161 k desc |
| MANE v1.5 (Ensembl) | GFF3 | 524,834 | 15.6 s | 45.1 s | 2.89× | 4.00 GB | 890 ±0% (n=5) | 136 ms / 156 k desc |
Measured on AMD EPYC 7702 64-Core Processor · 128 cores · 1007.22 GB RAM · Linux-5.14.0-503.15.1.el9_5.x86_64-x86_64-with-glibc2.34
Versions: Python 3.11.16 · gffbase 0.3.0 · duckdb 1.5.5 · pyarrow 25.0.1 · gffutils 0.14
Commit: 632a4d80dee0 · Run: 2026-09-27T15:07:53Z
Generated from benchmarks/results/06_mega.linux-x86_64.json by tools/gen_benchmark_tables.py. Do not edit by hand.
peak RSS is ingest plus exhaustive validation, not the cost of ingest:
validate_db defaults to sample=200 and the CLI never overrides it. No
speedup is published unless both engines' correctness signatures match first,
and every number is generated from a committed measurement file — a test fails
if a published table stops matching it. The per-corpus analysis, the fairness
constraints and the measured run-to-run spread are on the
performance and
methodology pages.
What's inside
- Rust + PyO3 parser — streaming, SIMD line and tab splitting,
percent-decoding in and encoding back out, GTF semicolon-in-quotes safe, gzip
and one-file tar archives transparent, failures raised as line-numbered
GFFFormatError. - Rust ingest producer — ids, duplicates and batching without a Python object per record, straight into DuckDB as Arrow; memory bounded by a budget.
- DuckDB columnar storage — an 11-table schema plus 3 compatibility views, set-based GTF gene/transcript synthesis, a materialized transitive closure, and a per-seqid-banded R-tree built inline during ingest.
- Smart routing —
region()picks the R-tree or a zone-map-pruned scan;children()andparents()look ids up in one table, and inside a loop over a gffbase iterator are prefetched. - Noisy input — byte-order marks, CR line endings, CDS-only and AUGUSTUS GTF, Liftoff ids, truncated gzip: read as meant, and reported (noisy files).
- Vectorized batched API —
children_batched,parents_batchedandregion_batchedreturnpyarrow.Table,pandas.DataFrameorpolars.DataFramestraight out of DuckDB's buffer pool. - Drop-in legacy API — plus
bed12,interfeatures, anexecute()SQL escape hatch andexport_sqlite(), with every remaining difference fromgffutils0.14 declared and tested. - Discontinuous features — several lines sharing one
IDare one logical feature, with per-segment phase,covered_lengthandexplode_segments=. - A command line and validation —
gffbase create|fetch|children|parents|region|search|rmdups|sanitize|validate|migrate, structural validation at two depths, and in-place migration of a v1 database.
Documentation
Full site: khchao.com/gffbase
| Page | What's there |
|---|---|
| Quickstart | A ten-minute walkthrough on a demo annotation |
| Migration guide | Drop-in checklist, and the one loop pattern to batch |
| Noisy files | What gffbase does with each non-standard input |
| Tuning | Threads, the memory budget, ingest stages, when to batch |
| Usage gallery | Every public method, copy-pasteable |
| Cookbooks | GENCODE/Ensembl, RefSeq, MANE, ML workflows |
| Performance | The numbers, and what they do not claim |
| Command line | Every gffbase subcommand |
| API reference | Full signatures and docstrings |
| FAQ and troubleshooting | Short answers; errors organized by message |
Contributing
Pull requests, bug reports and feature suggestions are welcome.
CONTRIBUTING.md covers the Rust and Python
development setup, the test suite and its coverage gates, branch naming and the
PR checklist. The repository ships
issue and
pull-request templates.
License
Apache License 2.0 — see LICENSE.
Citation
If GFFBase contributes to your research, please cite it:
@software{chao_gffbase_2026,
author = {Chao, Kuan-Hao},
title = {{GFFBase}: Rust-accelerated GFF3/GTF parser with a
DuckDB-backed storage engine and zero-copy PyArrow interface},
year = 2026,
version = {0.3.0},
url = {https://github.com/Kuanhao-Chao/gffbase},
}
The repository also ships a CITATION.cff, so
GitHub's "Cite this repository" button produces an up-to-date reference.
Per-version DOIs, when available, are tracked on the releases page.
Metadata
Release files for gffbase 0.3.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 | |
|---|---|---|---|
| gffbase-0.3.0.tar.gz | 973.1 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| gffbase-0.3.0-cp310-abi3-win_amd64.whl | CPython 3.10 | abi3 | Windows x86-64 | Details |
| gffbase-0.3.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl | CPython 3.10 | abi3 | Linux glibc 2.17+ x86-64 | Details |
| gffbase-0.3.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl | CPython 3.10 | abi3 | Linux glibc 2.17+ ARM64 | Details |
| gffbase-0.3.0-cp310-abi3-macosx_11_0_arm64.whl | CPython 3.10 | abi3 | macOS 11.0+ ARM64 | Details |
| gffbase-0.3.0-cp310-abi3-macosx_10_12_x86_64.whl | CPython 3.10 | abi3 | macOS 10.12+ x86-64 | Details |
Total release size: 4.0 MB
Release files / gffbase-0.3.0.tar.gz
| Download URL | gffbase-0.3.0.tar.gz |
|---|---|
| Size | 973.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
961a30f1baa3218ee0491f76217d4780f50e467ba078440930aecfad72779c4a
|
|
BLAKE2b-256 checksum How to use checksums |
bdbaae2b90d468bd4c13bca5722bf80ae5413b1093fa54a01ffa7feadce095f7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 27, 2026.
Transparency logRelease files / gffbase-0.3.0-cp310-abi3-win_amd64.whl
| Download URL | gffbase-0.3.0-cp310-abi3-win_amd64.whl |
|---|---|
| Size | 556.4 kB |
| Tags | CPython 3.10 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
7d6b4b3496fb34469b237734a063407e666cda6ab7922155bf72e16b0d812af5
|
|
BLAKE2b-256 checksum How to use checksums |
6414cc2bd575a575dfde9dfef2b263330718e7fae9769fc6a8b01f4fd07a8fd1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 27, 2026.
Transparency logRelease files / gffbase-0.3.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | gffbase-0.3.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 643.9 kB |
| Tags | CPython 3.10 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
718a926e2be6d105df7332f32830c361c742ea626f5c3eb041f7b8dd6b9d2898
|
|
BLAKE2b-256 checksum How to use checksums |
39b06a68e961f4119daf40f89e1fbfde4422c08fdb122f962786c8e8cd4f8dfb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 27, 2026.
Transparency logRelease files / gffbase-0.3.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | gffbase-0.3.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 635.9 kB |
| Tags | CPython 3.10 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
d99ed16e19ed5a12706b40c88e613f2000c8444979d885574d7573743d43c3ef
|
|
BLAKE2b-256 checksum How to use checksums |
112d6c9ecebf62094f2daf2eb0d5122b2343afa5ed9bae5d4a56ac2f5a06db9f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 27, 2026.
Transparency logRelease files / gffbase-0.3.0-cp310-abi3-macosx_11_0_arm64.whl
| Download URL | gffbase-0.3.0-cp310-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 610.7 kB |
| Tags | CPython 3.10 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
85c8cf75dee4bea214370550ca17b23834366506c600f9b776fe21d9a7bed81c
|
|
BLAKE2b-256 checksum How to use checksums |
3ffedd3955af555f5270b3acb048f75c3dd696857e247d633d90a6643526df4d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 27, 2026.
Transparency logRelease files / gffbase-0.3.0-cp310-abi3-macosx_10_12_x86_64.whl
| Download URL | gffbase-0.3.0-cp310-abi3-macosx_10_12_x86_64.whl |
|---|---|
| Size | 618.0 kB |
| Tags | CPython 3.10 abi3 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
b37d4cb2fc315f540a975a00c2c2796058a9347061a35db767c0254825714c9d
|
|
BLAKE2b-256 checksum How to use checksums |
f75178e407d3c0cdec9c983bfa73a5637a925dcfa32091e026d0133e357451c6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 27, 2026.
Transparency log