High-performance bioinformatics engine for Edge Computing — 5-bit encoding, vectorised NumPy core, optional C backend
Project description
BioForge — High-Performance Bioinformatics Engine
A bioinformatics engine built for Edge Computing.
No Biopython. No heavy dependencies. NumPy core + optional C engine for maximum speed.
Why this exists
Most bioinformatics tools are built for servers with gigabytes of RAM.
BioForge was built for the opposite: low-power hardware, minimal footprint,
maximum speed — running genetic analysis offline and locally.
Two core rules:
- Zero Python loops in the hot path — every operation is vectorised with NumPy.
- 5-bit encoding — every biological symbol fits in 5 bits, saving 37.5% memory vs ASCII.
Key numbers
| Operation | Result |
|---|---|
| Memory (30M bases) | 18.75 MB (37.5% less than plain ASCII) |
| Translation throughput | ~5 M amino acids / second (NumPy) · ~27× faster with C engine |
| NW alignment 1000×1000 nt | ~165 ms (NumPy) · ~29× faster with C engine |
| FASTA ingestion (C batch parser) | ~80 M bases / second |
| FASTQ ingestion (C batch parser) | ~14 M bases / s · ~94 K reads / s |
| QC filter 200 K reads (columnar) | 0.28 s — 18.6× faster than per-record |
| vs Biopython — QC filter | ~5–6× faster, identical result |
| vs Biopython — load all in RAM | ~6.9× less memory (115 MB vs 801 MB) · ~9.5× faster |
| Compressed input | .gz read transparently in C (zlib, static-linked) |
| Dependencies | NumPy (C engine included, pre-compiled) |
Architecture
┌──────────────────────────────────────────────────────────────┐
│ Level 3 — bioforge/aligner.py NW alignment │
│ Anti-diagonal wavefront O(m+n) · mutation detection │
├──────────────────────────────────────────────────────────────┤
│ Level 2 — bioforge/smart_translator.py DNA → Protein │
│ CODON_LUT + sliding_window_view · first-ATG ORF detection │
├──────────────────────────────────────────────────────────────┤
│ Level 1 — bioforge/biocore.py 5-bit storage │
│ BitPacker · PackedSequence · SmartImporter · LUTs │
├──────────────────────────────────────────────────────────────┤
│ C engine — bioforge/engine/engine.c Optional backend │
│ GCC -O3 -march=native -fopenmp · auto-loaded via ctypes │
└──────────────────────────────────────────────────────────────┘
The 5-bit unified alphabet
Every biological symbol — nucleotides, amino acids, gaps, stop codons and
ambiguous bases — fits in a single 5-bit scheme (32 states).
One encoding covers DNA, RNA, and proteins in the same pipeline.
State Symbol State Symbol
0 Adenine (A) 14 Methionine (M)
1 Cytosine (C) ... (all 20 amino acids: 4–23)
2 Guanine (G) 24 STOP codon (*)
3 Thymine / Uracil 25 Alignment gap (-)
4–23 Amino acids 31 Unknown / ambiguous
Installation
git clone https://github.com/erlanders177/bioforge.git
cd bioforge
pip install -r requirements.txt # only needs NumPy
Requirements
- Python ≥ 3.10
- NumPy ≥ 1.24 — the only runtime dependency
- The C engine ships pre-compiled (
engine.dll, zlib statically linked). If it can't load on your platform, BioForge falls back to NumPy automatically.
Optional — compile the C engine (27–29× faster on translation and alignment):
python bioforge/engine/build.py
Requires GCC. On Windows: MinGW-w64. On Linux/Mac: sudo apt install gcc / brew install gcc.
If not compiled, BioForge falls back to NumPy automatically — no code changes needed.
For development and testing:
pip install hypothesis pytest pytest-benchmark
Quick start
Import and encode a FASTA sequence
from bioforge import SmartImporter, SeqType
records = SmartImporter.from_string(""">gene_1
ATGGTGCACCTGACTCCTGAGGAGAAGTCTGCC
""")
seq = records[0]
print(seq.n_symbols) # 33
print(len(seq.data)) # 21 (37.5% smaller than ASCII)
print(seq.to_string()) # ATGGTGCACCTGACTCCTGAGGAGAAGTCTGCC
Stream a huge FASTA/FASTQ with constant RAM
from bioforge import SmartImporter
# One PackedSequence at a time — never loads the whole file
for seq in SmartImporter.stream("genome.fa"):
print(seq.header, seq.n_symbols)
# FASTQ yields FastqRecord (sequence + Phred qualities)
for rec in SmartImporter.stream_fastq("reads.fastq"):
if rec.passes_quality(20):
process(rec.sequence)
Quality-filter millions of reads — the fast lane (columnar)
from bioforge import SmartImporter
total = passed = 0
for batch in SmartImporter.stream_fastq_batches("reads.fastq"):
mask = batch.passes(20) # ONE NumPy op for thousands of reads
total += len(batch)
passed += int(mask.sum())
kept = batch.filter(mask) # new ReadBatch, no per-read objects
print(f"{passed}/{total} reads with mean quality >= 20")
stream_fastq_batches keeps a whole batch as contiguous matrices instead of
one object per read, so filtering 200 000 reads drops from ~5.3 s to ~0.28 s.
Materialise a single read only when you need it: batch[i] → FastqRecord.
Compressed .gz files are read transparently (decompressed in C):
for rec in SmartImporter.stream_fastq("reads.fastq.gz"): # no manual gunzip
...
Pass n_threads to go multi-core (an adaptive dispatcher picks the best path):
# plain → parallel parse · .gz → libdeflate (~2× faster) + parse
for batch in SmartImporter.stream_fastq_batches("reads.fastq.gz", n_threads=0):
... # n_threads: 1 = sequential (constant RAM) · >1 = threads · 0 = all cores
Reading compressed FASTQ is ~1.6× faster this way (libdeflate beats zlib); plain-file parse parallelism is memory-bandwidth bound, so its gain is modest on few cores but scales on many-core servers.
BGZF — parallel-decompressible .gz (~2× faster reads)
A BGZF file is a valid .gz (any gunzip reads it) but split into
independent 64 KB blocks, so BioForge decompresses it across all cores. Convert
once a file you'll process repeatedly:
python -m bioforge.bgzf reads.fastq # or: bioforge-bgzip reads.fastq
# → reads.fastq.gz (BGZF). Reads at ~113 M bases/s vs ~58 for plain .gz.
BioForge auto-detects BGZF and routes to the parallel path; plain .gz keeps
using single-thread libdeflate.
GC content and k-mer spectrum — vectorised over a whole batch
from bioforge import SmartImporter
spectrum = None
for batch in SmartImporter.stream_fastq_batches("reads.fastq"):
gc = batch.gc_content() # GC fraction per read (NumPy array)
s = batch.kmer_spectrum(k=4) # counts of all 4^4 k-mers in the batch
spectrum = s if spectrum is None else spectrum + s
# spectrum[i] = how many times k-mer #i appears across the whole file
Both run with zero per-read objects; ambiguous bases (N) are skipped from k-mers.
Fast FASTQ quality report (FastQC-style)
python -m bioforge.qcreport reads.fastq.gz # or: bioforge-qc reads.fastq.gz
One pass, constant RAM. Reports read/base counts, length, overall GC, mean
quality, %reads ≥ Q20/Q30, plus per-read quality and GC histograms,
per-position mean quality (the FastQC signature plot) and per-base
composition — all built on the columnar API. Use -o report.txt to save it.
Translate DNA to protein
from bioforge import SmartTranslator
protein = SmartTranslator.translate(seq)
print(protein.to_string()) # MVHLTPEEKSA
Detect mutations between two sequences
from bioforge import SequenceAligner, format_alignment
result = SequenceAligner.align(seq_ref, seq_query)
print(f"Identity: {result.identity:.1%}")
print(format_alignment(result))
for mut in result.mutations:
print(mut)
# Mutation(kind='substitution', pos_a=18, pos_b=18, sym_a='A', sym_b='T')
Map long reads to a genome (Level 4 — seed-chain-align)
Locate reads in a reference far beyond what the O(m·n) aligner can handle, minimap2-style: minimizer seeding → chaining (C DP) → banded extension.
from bioforge import GenomeAligner
mapper = GenomeAligner(reference_sequence, k=15, w=10) # builds the index once
for m in mapper.map(read):
print(m.to_paf()) # standard PAF, one line per mapping
# read1 1000 0 1000 + chr1 4600000 733120 734118 980 998 60 ...
print(m.strand, m.target_start, f"{m.identity:.1%}")
Handles both strands, tolerates mismatches/indels, and reports a mapping quality. The chaining dynamic program runs in the C engine (with a NumPy fallback).
Full mutation analysis pipeline (DNA + protein)
from bioforge import run, build_report
result = run("reference.fa", "query.fa", mode="both")
print(build_report(result))
Error handling
from bioforge import BioForgeError, TranslationError, SmartImporter, SmartTranslator
try:
for rec in SmartImporter.stream_fastq("reads.fastq.gz"):
protein = SmartTranslator.translate(rec.sequence)
except TranslationError as e:
print(f"Translation failed: {e}") # e.g. no ATG found
except BioForgeError as e:
print(f"BioForge error: {e}") # ANY engine error: parse, I/O, decompress…
One exception family. Every engine error subclasses BioForgeError, so a
single except BioForgeError catches them all — translation, alignment, parsing,
file I/O (BioForgeIOError), engine/decompression (EngineError). Each also
subclasses the matching builtin (ValueError, OSError, RuntimeError…), so
existing except OSError-style code keeps working.
Run the verifier (no coding knowledge required)
python check.py
Project structure
bioforge/ Python package — all core modules
__init__.py Public API entry point (from bioforge import ...)
biocore.py Level 1 — 5-bit storage engine
smart_translator.py Level 2 — DNA → protein translation
aligner.py Level 3 — pairwise alignment + mutation detection
analyze.py Full pipeline: DNA + protein analysis, report generation
qcreport.py Fast FASTQ quality report (FastQC-style, columnar)
bgzf.py BGZF converter (parallel block gzip) — bioforge-bgzip
engine/
engine.c C source — pack, unpack, NW align, translate (GCC -O3)
engine.dll Compiled C backend (Windows)
_loader.py ctypes wrapper with automatic NumPy fallback
check.py Non-programmer verifier (runs all checks automatically)
conftest.py Pytest fixtures shared across all tests
tools/
visor.py Interactive step-by-step translator (CLI)
comparador.py Sequence comparator tool (CLI)
stress_test.py 30M-base performance benchmark
bench_vs_biopython.py BioForge vs Biopython: time + RAM (FASTQ parse/QC/load)
tests/
test_biocore.py L1: property-based tests (Hypothesis) + benchmarks
test_translator.py L2: genetic code correctness + error paths
test_aligner.py L3: alignment properties + mutation detection
test_analyze.py Pipeline: full integration tests + CLI tests
test_streaming.py Streaming/batch parser + columnar API (Sequence/ReadBatch)
test_qcreport.py FASTQ quality report (qcreport.py)
docs/
architecture.md Design rules, levels, encoding details
api_reference.md Code examples for every module
benchmarks.md Measured numbers and methodology
roadmap.md Status and planned extensions
How the vectorisation works
Translation (Level 2)
① decode PackedSequence → uint8 array [0–3 per nucleotide]
② find first ATG → C engine scan / NumPy sliding_window_view
③ extract ORF, reshape → (N, 3) codon matrix
④ base-4 index → idx = n₁×16 + n₂×4 + n₃ (vectorised)
⑤ CODON_LUT[idx] → amino acid array (single fancy-index)
⑥ argmax on STOP mask → truncate at stop codon
Alignment (Level 3)
Needleman-Wunsch has a cell-level data dependency that prevents full 2D vectorisation. The solution: anti-diagonal wavefront.
Cells on the same anti-diagonal (i + j = d) are mutually independent,
so each diagonal is a single vectorised operation.
Python-level iterations: O(m+n) instead of O(m·n).
When the C engine is available, the entire DP matrix is computed in C with OpenMP, giving ~29× speedup over the NumPy wavefront.
C engine
bioforge/engine/engine.c provides optimised implementations of all hot-path
operations. Loaded automatically via ctypes at import time.
If engine.dll is missing, all code falls back to NumPy silently.
from bioforge.engine._loader import C_AVAILABLE
print(C_AVAILABLE) # True if C engine loaded, False if using NumPy fallback
Running the tests
# Full test suite (269 tests)
pytest tests/ -v
# Benchmarks only
pytest tests/ --benchmark-only
# Quick smoke check (no coding knowledge required)
python check.py
Known limitations
| Limitation | Detail |
|---|---|
| Aligner memory (full NW) | O(m·n) matrix — sequences > 15 000 bp may exhaust RAM. Use band=N for large sequences. |
| Protein auto-detection | Sequences without E/F/I/L/P/Q/* are classified as nucleotides. Use force_type=SeqType.PROTEIN to override. |
| C engine | Pre-compiled .dll/.so not included. Run python bioforge/engine/build.py to compile. Requires GCC. |
| Banded NW (NumPy fallback) | Without the C engine, banded NW uses the full matrix with NEG_INF masking — same result, standard RAM. |
Roadmap
- Level 1 — 5-bit storage, FASTA parser, SmartImporter
- Level 2 — vectorised genetic code translation (C + NumPy)
- Level 3 — Needleman-Wunsch alignment + mutation detection (C + NumPy)
- Full mutation analysis pipeline (DNA + protein, 3 modes)
- BioForgeError exception hierarchy for library users
- Reverse complement vectorised —
PackedSequence.reverse_complement() - 6-frame translation —
SmartTranslator.translate_all_frames() - Banded NW —
SequenceAligner.align(seq_a, seq_b, band=N) - Smith-Waterman local alignment —
SequenceAligner.align_local() - Streaming FASTA/FASTQ parser in C —
SmartImporter.stream()/stream_fastq() - Batch parser (5-bit encoding in C) — ~80 M bases/s FASTA, ~94 K reads/s FASTQ
- Columnar QC API —
stream_fastq_batches()·ReadBatch.passes()/filter() - Compressed
.gzdecoded in C (zlib, static-linked, transparent) - Object-free columnar k-mer spectrum + per-read GC —
kmer_spectrum()/gc_content() - Benchmark vs Biopython —
tools/bench_vs_biopython.py - Fast FASTQ quality report (FastQC-style) —
bioforge-qc/bioforge.qcreport - Adaptive multi-core dispatcher —
n_threads=: parallel parse + libdeflate.gz - BGZF parallel-decompressible
.gz+ converter —bioforge-bgzip - Native per-platform wheels on PyPI (cibuildwheel)
- Long-read / genome-scale aligner (k-mer seeding)
References & inspiration
BioForge's genome mapper (Level 4) is an independent, from-scratch implementation of well-established, published algorithms. No third-party source code is included or copied — only the ideas from the scientific literature, which is what publishing them is for. With gratitude to:
- Minimap2 — Li, H. (2018). Minimap2: pairwise alignment for nucleotide
sequences. Bioinformatics, 34(18), 3094–3100. The seed-chain-align strategy
and the chaining dynamic program that inspired
genomemap.py. (paper · MIT-licensed source) - Minimizers — Roberts, M., Hayes, W., Hunt, B. R., Mount, S. M., &
Yorke, J. A. (2004). Reducing storage requirements for biological sequence
comparison. Bioinformatics, 20(18), 3363–3369. The (w, k) minimizer sampling
behind
minimizers.py. - Needleman–Wunsch (1970) and Smith–Waterman (1981) — the classic dynamic-programming alignments behind Level 3.
BioForge is not affiliated with or endorsed by the authors of the above.
Author
Aarón Aranda Torrijos — github.com/erlanders177
License
PolyForm Noncommercial 1.0.0 — free for personal, academic and research use.
Commercial use requires explicit permission from the author.
See LICENSE for full terms.
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
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file bioforge-3.3.0.tar.gz.
File metadata
- Download URL: bioforge-3.3.0.tar.gz
- Upload date:
- Size: 476.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
858ef05852b60275fb1a93a1d9faff4b982b54adb4b951d1a3472b14a3233f3a
|
|
| MD5 |
253f46a521b529b3352ee7b0805a3243
|
|
| BLAKE2b-256 |
e2b9e3dd881eaf245ec7bbebbec26aa1596e91b9cb39d0c63e334e0ff9c6d7b7
|
Provenance
The following attestation bundles were made for bioforge-3.3.0.tar.gz:
Publisher:
wheels.yml on erlanders177/bioforge
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bioforge-3.3.0.tar.gz -
Subject digest:
858ef05852b60275fb1a93a1d9faff4b982b54adb4b951d1a3472b14a3233f3a - Sigstore transparency entry: 2102836837
- Sigstore integration time:
-
Permalink:
erlanders177/bioforge@75f0b0830414621e39b7374e2bdd29e38b739db5 -
Branch / Tag:
refs/tags/v3.3.0 - Owner: https://github.com/erlanders177
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
wheels.yml@75f0b0830414621e39b7374e2bdd29e38b739db5 -
Trigger Event:
push
-
Statement type:
File details
Details for the file bioforge-3.3.0-py3-none-win_amd64.whl.
File metadata
- Download URL: bioforge-3.3.0-py3-none-win_amd64.whl
- Upload date:
- Size: 445.2 kB
- Tags: Python 3, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
05f6067250c7f28db0ff0343f04c9fed00a548106f12582ed96a2f3cb036827a
|
|
| MD5 |
cd0b19ee9810b408825b3878d49bf1c9
|
|
| BLAKE2b-256 |
499635833315aaa2699e5ca62fb2caa7df088bc5a6feb0765196024e0b9b527b
|
Provenance
The following attestation bundles were made for bioforge-3.3.0-py3-none-win_amd64.whl:
Publisher:
wheels.yml on erlanders177/bioforge
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bioforge-3.3.0-py3-none-win_amd64.whl -
Subject digest:
05f6067250c7f28db0ff0343f04c9fed00a548106f12582ed96a2f3cb036827a - Sigstore transparency entry: 2102837999
- Sigstore integration time:
-
Permalink:
erlanders177/bioforge@75f0b0830414621e39b7374e2bdd29e38b739db5 -
Branch / Tag:
refs/tags/v3.3.0 - Owner: https://github.com/erlanders177
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
wheels.yml@75f0b0830414621e39b7374e2bdd29e38b739db5 -
Trigger Event:
push
-
Statement type:
File details
Details for the file bioforge-3.3.0-py3-none-manylinux_2_28_x86_64.whl.
File metadata
- Download URL: bioforge-3.3.0-py3-none-manylinux_2_28_x86_64.whl
- Upload date:
- Size: 461.7 kB
- Tags: Python 3, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
874db874c6552d92b380a9d1ef6d5c231f318027268255bcedff6a00ccd37a0e
|
|
| MD5 |
8adf98cd37a5ba9e2b5352699cf89fa9
|
|
| BLAKE2b-256 |
1f68c21a9dbc33ff3c71655eb9bfdc270f2e3625e3817b030fbe3cb9d086d35a
|
Provenance
The following attestation bundles were made for bioforge-3.3.0-py3-none-manylinux_2_28_x86_64.whl:
Publisher:
wheels.yml on erlanders177/bioforge
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bioforge-3.3.0-py3-none-manylinux_2_28_x86_64.whl -
Subject digest:
874db874c6552d92b380a9d1ef6d5c231f318027268255bcedff6a00ccd37a0e - Sigstore transparency entry: 2102837103
- Sigstore integration time:
-
Permalink:
erlanders177/bioforge@75f0b0830414621e39b7374e2bdd29e38b739db5 -
Branch / Tag:
refs/tags/v3.3.0 - Owner: https://github.com/erlanders177
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
wheels.yml@75f0b0830414621e39b7374e2bdd29e38b739db5 -
Trigger Event:
push
-
Statement type:
File details
Details for the file bioforge-3.3.0-py3-none-macosx_11_0_arm64.whl.
File metadata
- Download URL: bioforge-3.3.0-py3-none-macosx_11_0_arm64.whl
- Upload date:
- Size: 638.9 kB
- Tags: Python 3, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
96246f6e5f35c5990c6a54187dd84e027d059ab5688e179f053ccdd9a26647fd
|
|
| MD5 |
6babd27623da2f244b4108aec0b0cbf0
|
|
| BLAKE2b-256 |
1be2f0e790250e9a0ba84a1177b06e4d97b4a80a45dd840979835b50b332291c
|
Provenance
The following attestation bundles were made for bioforge-3.3.0-py3-none-macosx_11_0_arm64.whl:
Publisher:
wheels.yml on erlanders177/bioforge
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bioforge-3.3.0-py3-none-macosx_11_0_arm64.whl -
Subject digest:
96246f6e5f35c5990c6a54187dd84e027d059ab5688e179f053ccdd9a26647fd - Sigstore transparency entry: 2102837413
- Sigstore integration time:
-
Permalink:
erlanders177/bioforge@75f0b0830414621e39b7374e2bdd29e38b739db5 -
Branch / Tag:
refs/tags/v3.3.0 - Owner: https://github.com/erlanders177
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
wheels.yml@75f0b0830414621e39b7374e2bdd29e38b739db5 -
Trigger Event:
push
-
Statement type: