biotapy#
biotapy is a microbiome analysis toolkit for Python, in the style of R’s mia and phyloseq, built on AnnData/TreeData. Samples are always rows, the count matrix stays sparse, the phylogenetic tree sits alongside the data as a first-class object, and every computation with an R equivalent is checked against R on real data.
Status#
biotapy 0.2 is an early release. The API can still change between minor versions.
What 0.2 does (full signatures in the API reference):
Readers:
bt.io.read_biom(BIOM 1.0/2.1),bt.io.read_qiime2(.qzaartifacts, no QIIME 2 install needed),bt.io.read_dada2(CSV/TSV/.rdssequence tables),bt.io.read_phyloseq(.rds/.RData, no R needed) andbt.io.read_metaphlan(MetaPhlAn 3 and 4 profiles) all read into oneTreeData.bt.io.read_humannandbt.io.read_picrust2read function tables into aMuDatawith a community and a per-taxon modality;bt.io.read_picrust2_traitsreads PICRUSt2’s per-ASV gene copy numbers.Writer:
bt.io.write_biomwrites a BIOM 2.1 or 1.0 table back out.Datasets:
bt.datasets.toyandbt.datasets.toy_humann(in-memory, for examples and tests),bt.datasets.global_patterns,bt.datasets.enterotypeandbt.datasets.esophagus(phyloseq’s example datasets),bt.datasets.hmp2(the HMP2 inflammatory bowel disease cohort) andbt.datasets.enzyme(the ENZYME EC hierarchy), downloaded and cached on first use.Preprocessing:
bt.pp.relative,bt.pp.tax_glom,bt.pp.filter_features,bt.pp.filter_samplesandbt.pp.rarefy.Function:
bt.fn.load_hierarchy,bt.fn.func_glomandbt.fn.renorm(checked against HUMAnN’s own output),bt.fn.contributionsandbt.fn.functional_redundancy.Tools:
bt.tl.alpha,bt.tl.beta,bt.tl.unifrac,bt.tl.pcoa,bt.tl.nmdsandbt.tl.permanova, each checked against R on real data.Plots:
bt.pl.bar,bt.pl.richness,bt.pl.ordination,bt.pl.scree,bt.pl.heatmapandbt.pl.contributions.
Next, in 0.3: compositional transforms (CLR, PhILR) and differential abundance (ANCOM-BC, LinDA, ALDEx2, MaAsLin 3) behind one result format. See the roadmap; no dates are promised.
Installation#
You need Python 3.12 or newer.
pip install biotapy
or, with uv:
uv add biotapy
or, with pixi, in a workspace that has Python 3.12 or newer:
pixi add "python>=3.12"
pixi add --pypi biotapy
The development version installs straight from GitHub:
pip install git+https://github.com/pedrocr83/biotapy.git.
On Python 3.14, the biom-format dependency has no wheels yet, so it is built
from source and needs a C compiler until biom-format publishes 3.14 wheels
(biocore/biom-format#1004).
Quick start#
Load the bundled toy dataset, add relative abundance, and aggregate to phylum:
import biotapy as bt
tdata = bt.datasets.toy()
tdata.shape # (6, 8): 6 samples, 8 features
rel = bt.pp.relative(tdata)
rel.layers["relative"][0].sum() # 1.0, X itself is untouched
glom = bt.pp.tax_glom(tdata, "phylum")
glom.n_vars # 3: features sharing a lineage down to phylum are merged
Reading your own data#
Each reader returns a TreeData following the same data model.
Only the first argument is required; the keyword arguments attach taxonomy,
sample metadata and a phylogenetic tree where the format supports them.
# BIOM 1.0 (JSON) or 2.1 (HDF5), dialect detected automatically
tdata = bt.io.read_biom("table.biom", tree="tree.nwk")
# QIIME 2 artifacts (.qza), no QIIME 2 install required
tdata = bt.io.read_qiime2(
"table.qza", taxonomy="taxonomy.qza", tree="tree.qza", metadata="sample-metadata.tsv"
)
# DADA2 sequence tables: CSV, TSV or R's .rds, with optional taxonomy and tree
tdata = bt.io.read_dada2("seqtab.rds", taxa="taxa.rds", tree="tree.nwk")
# phyloseq objects saved from R with saveRDS()/save() - no R, no rpy2
tdata = bt.io.read_phyloseq("ps.rds")
# an .RData file can hold several phyloseq objects; pick one by its R variable name
tdata = bt.io.read_phyloseq("ps.RData", name="ps_16S")
Write back out to BIOM with bt.io.write_biom(tdata, "table.biom").
Example datasets#
bt.datasets.global_patterns(), bt.datasets.enterotype() and
bt.datasets.esophagus() download phyloseq’s example datasets once and cache
them on disk with pooch; later calls reuse the cache with no network
access, as long as the hash still matches. Set BIOTAPY_DATA_DIR to change
the cache directory:
import biotapy as bt
gp = bt.datasets.global_patterns() # 26 samples, 19,216 OTUs
gp.shape
Saving your work#
A TreeData round-trips through treedata’s own format, tree included:
tdata.write_h5td("tdata.h5td")
import treedata as td
back = td.read_h5td("tdata.h5td")
Dropping down to plain AnnData (no tree) works the usual way too:
tdata.write_h5ad("tdata.h5ad") / anndata.read_h5ad("tdata.h5ad").
The data model#
Every biotapy function reads and writes the same object, a TreeData (an
AnnData that also carries a phylogeny):
Slot |
Holds |
|---|---|
|
Samples x features, sparse CSR |
|
Sample metadata |
|
Taxonomy, one column per rank: |
|
The phylogenetic tree, leaves named after your features |
|
Relative abundance, added by |
|
|
See the data model guide for the full slot list (including the ones diversity and ordination write) and the data-model-slots contract for the exact rules.
Every function is pure by default: it returns a new object or its result and
leaves the one you passed in unchanged. Only a tl function called with
inplace=True writes its result into it (obs, obsp, obsm and
uns["biotapy"]).
Coming from R#
Every function’s docstring names its R equivalent (phyloseq::tax_glom,
mia::agglomerateByRank, and so on) in its Notes section, and the
Coming from R page lists them all, with the phyloseq accessors
that are plain AnnData code. The phyloseq analysis vignette is
redone with biotapy in the tutorials.
Example data and licensing#
bt.datasets.global_patterns, bt.datasets.enterotype and
bt.datasets.esophagus download example data from
phyloseq’s repository at runtime; biotapy ships none of it.
That data stays licensed to phyloseq’s authors under AGPL-3.
bt.datasets.enzyme downloads ENZYME, distributed by the SIB Swiss Institute
of Bioinformatics under CC BY 4.0. bt.datasets.hmp2 downloads the HMP2
tables from the IBDMDB, which states no licence for them; cite
Lloyd-Price et al. (2019, Nature 569:655-662) when you use them. biotapy
itself is BSD-3-Clause.
Documentation#
Full documentation, including the user guide and API reference, is at biotapy.readthedocs.io.
Development#
uv sync --group dev --group test --group doc
uvx prek run --all-files
uv run --group test pytest
Network and golden tests (downloads data, compares against R) are excluded by default; run them explicitly with:
uv run --group test pytest -m "network or golden"
Regenerating the R golden files themselves needs the pinned R container - see the regenerate-golden-files playbook.
All contributions follow rules.md and the knowledge bundle (decisions, contracts, roadmap).
Release notes#
See the changelog.
Contact#
Questions, bug reports and feature requests all go to the issue tracker.
Citation#
t.b.a