Make your files agree on names before they break your pipeline.
Your bioinformatics files never agree on identifiers. The tree has homo_sapiens_GRCh38, the alignment has GRCh38.p14, the metadata calls it Human. The conversion tools don't care — they'll happily produce broken output. You spend hours manually reconciling labels so the pipeline doesn't silently fail.
Existing tools either handle format conversion (bioconvert, samtools, seqkit) or species-name reconciliation (PhyloMatcher, prepR4pcm). No tool does both, and nobody handles the real-world cases: assembly nicknames, accession-to-name mappings, institution-specific naming conventions.
biox detects mismatched identifiers across your files, applies multiple layers of matching logic, and produces a mapping document that any downstream tool can consume.
$ biox match sequences.fasta tree.nwk metadata.csv -o mapping.json
fasta tree matched by
────────────────────────────────────────────
GRCh38.p14 homo_sapiens_GRCh38 curated (GRCh38 → human assembly)
mm10 mus_musculus curated (mm10 → mouse assembly)
danio_rerio danio_rerio exact
rnor6 Rattus_norvegicus_6 fuzzy (92%) + curated confirmation
✓ 4/5 identifiers matched. 1 orphan: Oryzias_latipes (fasta only)No format conversion. No canonical model. Just a JSON mapping of which labels mean the same thing.
biox solves the matching problem in layers, because string distance alone is useless:
| Layer | What it catches | Example |
|---|---|---|
| Exact | Identical strings | danio_rerio ⇄ danio_rerio |
| Normalized exact | Same after case/separator normalization | Homo_Sapiens ⇄ homo-sapiens |
| Fuzzy | Close strings (conservative: token-Dice + number-aware) | reordering, typos in alphabetic names |
| Authority: NCBI | Taxids, accessions, assembly names, genome codes → taxid | mm10 ⇄ mus_musculus ⇄ 10090 ⇄ GRCm39 |
| Authority: GBIF | Scientific names + synonyms → backbone usageKey | Homo capensis → Homo sapiens |
| Crosswalk | Bridges authority key spaces (GBIF key ⇄ NCBI taxid) | merges the two authorities into one answer |
homo_sapiens_GRCh38 ⇄ GRCh38.p14 is not a fuzzy match — the strings barely overlap. The NCBI authority resolves both to taxid 9606 (Homo sapiens). mm10 ⇄ mus_musculus is the same: the authority knows UCSC genome codes and assembly accessions. These are the hard cases, and they're what biox is built for.
Authorities are stackable and configurable — a pluggable, ordered list of backends. The matcher runs string layers first, then each authority in turn, then the crosswalk merges across key spaces. Data is downloaded on demand via biox fetch (NCBI + GBIF dumps, ~700 MB total, cached locally). Nothing is bundled in the wheel.
pip install bioxFrom source:
git clone https://github.com/james-burgess/biox.git
cd biox
pip install -e '.[dev]'All authorities use public dumps or open REST APIs — no API keys or accounts needed.
biox fetch all # download all available authority dumps (~1 GB, one-time)
biox fetch ncbi # NCBI only (~225 MB)
biox fetch gbif # GBIF only (~466 MB)
biox fetch uniprot # UniProt species list (~1 MB)
biox fetch gtdb # GTDB bacteria + archaea (~50 MB)
biox fetch itis # ITIS SQLite (~200 MB)
biox fetch col # Catalogue of Life (~300 MB)
biox fetch silva # SILVA (creates dir, user provides FASTA)Data lands in data/raw/ by default. Set BIOX_DATA_DIR=/path/to/wherever to change it.
New to biox? Walk through the full workflow — from mismatched labels to clean format conversion — in the demo notebook. It runs in seconds without downloading authority data and covers the biox → bioconvert pipeline end-to-end.
# Download authority data (first run only)
biox fetch all
# Match identifiers across any files → produces mapping.json
biox match data/sequences.fasta data/tree.nwk -o mapping.json
# Inspect the mapping
biox mapping --ids mapping.json # list canonical identifiers
biox mapping --rename mapping.json # label → canonical pairs
biox produces the mapping; any converter consumes it. See the
**[Related Tools](#related-tools)** table for the full ecosystem.
---
## Architecture
biox/
├── core/
│ ├── model.py # Identifier, Source, Match, Confidence
│ └── mapping.py # Mapping JSON contract (pydantic-validated)
├── matching/
│ ├── registry.py # Identifier extraction seam (fasta/newick/generic)
│ ├── pipeline.py # Cascade runner: exact -> norm -> fuzzy -> auth -> crosswalk
│ ├── layers/
│ │ ├── exact.py # Exact + normalized matching
│ │ └── fuzzy.py # Conservative fuzzy (token-Dice + number-aware)
│ └── authorities/
│ ├── base.py # Authority protocol, AuthorityResult, AuthorityStack
│ ├── ncbi.py # NCBI taxid authority (assembly_summary + taxonomy dump)
│ ├── gbif.py # GBIF backbone dump authority (Simple DwC)
│ └── crosswalk.py # Bridges key spaces + appendable store
├── data.py # biox fetch — download-on-start provisioning
├── formats/ # (Phase 2 — per-format readers/writers)
└── cli/
└── main.py # match / mapping / fetch / convert(stub)
## Measured Performance
Calibrated against a real-world corpus of **477 labels / 3,511 ground-truth pairs** mined from live NCBI, UCSC, Ensembl, and GBIF data (see `tests/data/corpus/`):
| Configuration | Precision | Recall | F1 |
|---|---|---|---|
| String layers only (exact + norm + fuzzy) | 0.968 | 0.086 | 0.158 |
| + NCBI authority (local dumps) | 0.972 | 0.861 | 0.913 |
| + GBIF authority + crosswalk | **1.000** | **0.880** | **0.936** |
String distance tops out at ~9% recall. The authority layer is where the real work happens — it resolves the identifiers (taxids, accessions, assembly names, genome codes) that no string algorithm can reach.
Reproduce: `python scripts/measure.py` (after `biox fetch`).
---
## Related Tools
| Tool | What it does | Gap vs biox |
|---|---|---|
| **bioconvert** | 50 format, 100+ direct conversions | No identifier matching. Converts labels verbatim. |
| **PhyloMatcher** | Taxonomic name resolution via NCBI/GBIF | Phylogenetics only. Species names only. |
| **prepR4pcm** | Species name reconciliation in R | R-only. Trees vs trait data only. |
| **samtools / seqkit / etc.** | Single-domain format tools | No cross-file awareness at all. |
biox is the tool that sits *before* any of these — it gives you a mapping you can feed into anything.
---
## License
MIT — Copyright (c) 2025 James Burgess. See [LICENSE](LICENSE).
## Citation
If you use biox in your research, please cite it:
@software{burgess_biox, author = {James Burgess and Robert Saddler}, title = {biox — BioCross}, year = {2025}, url = {https://github.com/james-burgess/biox}, }