Skip to main content

bifti

A Python package for the BIfTI phantom format: parse/serialize the phantom JSON, load a phantom into plain NumPy arrays, and fetch phantoms from the public registry.

from bifti import NumpyPhantom

phantom = NumpyPhantom.load("subj42-3T.json")
tissue = phantom.tissues["gm"]  # a NumpyTissue: density, T1, T2, ... as np.ndarray
print(tissue.shape, tissue.T1.mean())

phantom.config is the parsed BiftiPhantom (the raw JSON structure: units, system, tissue definitions) — see phantom.py for the full data model, and loader.py for how each property resolves to an array.

API at a glance

Everything below is importable from the top-level bifti package (from bifti import ...):

Name What it is
NumpyPhantom.load(path, *, max_substeps=8) Load a phantom JSON + its NIfTIs into NumpyPhantom(config, tissues). max_substeps caps the quadrature samples per axis when an oblique reslice_to is resampled; raise it when the ObliqueResampleWarning says the result is under-sampled.
NumpyTissue One tissue as NumPy arrays: density, T1, T2, T2dash, ADC, dB0, B1_tx, B1_rx, plus .shape/.affine.
NumpyPhantom.save(dir, json_name="phantom.json", *, constant_threshold=None) Save a loaded phantom as a self-contained folder (float64 / complex128 NIfTIs named after the JSON + JSON, no reslice_to, no func; near-constant maps become constants with constant_threshold); see Saving. Returns the JSON path.
BiftiPhantom.load(path) / .save(path) Parse/serialize just the JSON side (no NIfTI I/O) — BiftiPhantom(units, system, tissues, reslice_to, schema).
load_catalog() Fetch and parse the public catalog.json — the discovery list, mapping a label to an immutable registry name.
load_registry() Fetch and parse the public registry.json — the immutable archive of every collection.
load_registry_phantom(collection, name) Download one phantom's JSON + NIfTIs from Zenodo into a local cache; returns the JSON path. collection is an immutable registry name.

NumpyPhantom.load is what you want for simulation/analysis (arrays); use BiftiPhantom directly only if you're generating or editing phantom JSONs without touching pixel data (e.g. examples/make_numerical_brain_cropped_bifti.py).

Installation

From PyPI:

# using uv (recommended):
uv add bifti
# or using pip:
pip install bifti

Or the latest unreleased version from git:

uv add --git https://github.com/mrx-org/bifti-phantoms --subdirectory python/bifti bifti
pip install "git+https://github.com/mrx-org/bifti-phantoms.git#subdirectory=python/bifti"

Examples

examples/ has a small, self-contained demo that loads a BIfTI phantom and plots every tissue's data — a starting point for seeing the package in action.

git clone https://github.com/mrx-org/bifti-phantoms
uv add --path bifti-phantoms/python/bifti bifti
File Purpose
examples/demo.py Load a phantom and plot one figure per tissue.
examples/nifti_to_koma.py Convert a phantom to a KomaMRI .phantom HDF5 file.
examples/mrzero_sim.py Simulate a Pulseq sequence on a phantom with MR-zero.
examples/make_numerical_brain_cropped_bifti.py Port the legacy MRzero test phantom to BIfTI.
examples/data/ Phantom JSONs + the NIfTIs they reference.
examples/data/generate.py Regenerates the example data in examples/data/ (reproducible).

Requirements

The core package only needs bifti's own dependencies (numpy, nibabel, requests). Resampling uses torch when it is importable — on CPU as well as CUDA — and NumPy otherwise; install it with the torch extra (pip install "bifti[torch]") or force a backend with BIFTI_RESAMPLE_BACKEND=numpy|torch. The examples pull in extra, examples-only dependencies (matplotlib, h5py, MRzeroCore, torch) declared as a dependency group rather than real package dependencies:

uv sync --group examples

Running

From this python/bifti directory:

# list the registry, pick one, download + plot
uv run --group examples examples/demo.py
# ...or plot a local phantom JSON directly
uv run --group examples examples/demo.py examples/data/shapes.json
uv run --group examples examples/demo.py examples/data/shapes_resliced.json
uv run --group examples examples/demo.py examples/data/shapes_downsampled.json

With no argument, demo.py fetches the live catalog.json, resolves each label to its registry.json collection, prints their phantoms as a numbered list, and downloads the one you pick (its JSON and every NIfTI it references) into examples/cache/ via bifti.registry before plotting. Passing a local JSON path skips the catalog and plots that file directly (the example data is committed in examples/data/).

demo.py saves one PNG per tissue into examples/figures/ and, on a GUI backend, also shows them. Each figure tiles the tissue's maps — density, T1, T2, T2', ADC, dB0, and every B1+/B1- channel — at the volume's middle slice. Spatially uniform properties show as a flat field; properties left at their default (e.g. T1 = inf) are blanked out.

The example data

The NIfTIs in examples/data/ are committed, but they are all produced by examples/data/generate.py — re-run it (uv run --group examples examples/data/generate.py) to regenerate them. It derives everything from a fixed seed and simple meshgrid functions (smooth bumps, low-order polynomials, a little noise), so re-running reproduces byte-identical files. The phantoms together exercise the whole format:

  • subj42-3T.json (hand-written) — a brain-like single slice. Uses reslice_to, so all maps are resampled from their native 64×64 grid onto a 100×100 grid on load. Exercises: scalar properties, a shared dB0 map, an 8-channel B1+, and a transformed reference (fat.dB0 = "x - 420").
  • shapes.json (generated) — a small 40×32×4 phantom with no reslice_to, so it loads on its native grid. Exercises: multiple tissues sharing one grid, a polynomial dB0 map, a 2-channel B1+, a func mapping ("x * 0.5 + 10"), property defaults, and a true 3D volume.
  • shapes_resliced.json (generated) — the same NIfTIs as shapes.json but with a reslice_to onto a finer grid (40×32×4 → 60×48×4), so loading genuinely resamples the 3D volumes.
  • shapes_downsampled.json (generated) — the same NIfTIs again, resliced onto a coarser grid (40×32×4 → 16×12×3) whose FOV deliberately overhangs the source. Exercises the case plain interpolation gets wrong: output voxels that average many source voxels, and output voxels that straddle the edge of the source FOV.

Note: loading a tissue with a func mapping prints a warning — the loader evaluates func with eval for brevity, so only load phantoms you trust (see the note in bifti/loader.py).

Known limitations

  • Complex-valued NIfTI data isn't handled. A complex B1+/B1- map gets cast with np.asarray(..., dtype=np.float64) in loader.py, which silently discards the imaginary part (numpy emits a ComplexWarning, easy to miss). The Rust crate fails loudly instead in this case.
  • Only the default units are accepted.

See also

Metadata

Release files for bifti 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for bifti 0.3.0
File Size Uploaded Provenance Actions
bifti-0.3.0.tar.gz 28.8 kB With provenance Details for bifti-0.3.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for bifti 0.3.0
File Interpreter ABI Platform Actions
bifti-0.3.0-py3-none-any.whl Python 3 none any Details for bifti-0.3.0-py3-none-any.whl

Total release size: 60.1 kB

Release files / bifti-0.3.0.tar.gz

Download URL bifti-0.3.0.tar.gz
Size 28.8 kB
Tags Source
SHA-256 checksum
How to use checksums
fa9521cd639fe9ee02325bd7085b70cbae48e76425b81ac801b430539d08258f
BLAKE2b-256 checksum
How to use checksums
a4197102ee07ce187e9729a8cc5b37d97a4250376c05b79a13afba864d78423d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 Oct 28, 2026.

Transparency log

Release files / bifti-0.3.0-py3-none-any.whl

Download URL bifti-0.3.0-py3-none-any.whl
Size 31.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3b25cf55a5e35c177e7b3538a32e1bfe795c4b4d6829864338f47f88c10425bd
BLAKE2b-256 checksum
How to use checksums
5a7ddbaf0fb2433eefa948286e74a8468164490da2b953496915fa791d425d47
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 Oct 28, 2026.

Transparency log

Security for bifti 0.3.0

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.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for bifti-0.3.0.tar.gz

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 Oct 28, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page