pyNiftiReg
A PyTorch reimplementation of NiftyReg-style image
registration, extracted from the drift-aug project. It runs on CPU or GPU and needs no NiftyReg
binaries.
For a reference image A and a floating image B it computes:
- An affine (or rigid) transform in world mm, using NiftyReg's convention
Affine * A_world = B_world, likereg_aladin. It maximises the similarity with Adam over an image pyramid, starting from aligned centres of mass. At the coarsest level it tries two starts: identity scale and moment-matched scale. - A stationary velocity field (SVF) on A's voxel grid, like
reg_f3d -vel. The field is parametrised by a cubic B-spline control-point grid. The loss is the (symmetric) NMI, LNCC or SSD betweenB_aligned ∘ exp(v)and A, plus NiftyReg-style bending energy, linear elasticity and an optional log-Jacobian penalty. The control-point spacing doubles at each coarser pyramid level and is refined exactly between levels.
It is NiftyReg-style, not a line-by-line port. The regularisation weights are normalised
differently from reg_f3d's. To reuse -be/-le/-jl values, convert them with
from_niftyreg_weights (multipliers ×5/×5/×50, calibrated on real breast and thorax MRI).
NMI values in qc come from this package's Parzen estimator and cannot be compared with
reg_measure.
Install
pip install -e . # numpy + torch
pip install -e '.[io]' # + nibabel, for NIfTI files
pip install -e '.[n4]' # + SimpleITK, for N4 bias correction in pyniftireg.preprocess
uv sync --extra dev # development: pytest, ruff, mypy, all extras
Usage
from pyniftireg import TorchReg, TorchRegParams, from_niftyreg_weights
from pyniftireg.flow import exp
from pyniftireg.grid import warp
from pyniftireg.io import load_nifti, save_nifti
from pyniftireg.preprocess import resample_to
params = TorchRegParams(
cp_spacing=-5.0, # NiftyReg convention: mm if positive, voxels if negative
similarity="nmi",
**from_niftyreg_weights(bending_energy=0.001, linear_elasticity=0.01, jacobian_log=0.0),
)
reg = TorchReg(params)
result = reg.register("A.nii.gz", "B.nii.gz", reference_mask="A_mask.nii.gz")
result.affine # (D+1, D+1) world-mm matrix, Affine @ A_world = B_world
result.velocity # (1, D, *A.shape) SVF in A's voxel units
result.jacobian # det J statistics of exp(velocity)
result.qc # NMI before/after the non-rigid step, timings
# Warp B onto A
a, sa = load_nifti("A.nii.gz")
b, sb = load_nifti("B.nii.gz")
b_aligned = resample_to(b, sb, sa, affine=result.affine)
b_on_a = warp(b_aligned, exp(result.velocity))
save_nifti("B_on_A.nii.gz", b_on_a, sa)
register also takes numpy arrays or torch tensors of shape (*spatial) or (1, 1, *spatial),
for the images and the masks, and paths and arrays can be mixed. Give an array's grid with
reference_space= / floating_space= (an ImageSpace). Without one, the array is taken to have
1 mm voxels and identity orientation:
import numpy as np
from pyniftireg import ImageSpace
a = np.load("A.npy") # (H, W, D)
b = np.load("B.npy")
result = reg.register(a, b, reference_space=ImageSpace.from_spacing(a.shape, (0.8, 0.8, 2.0)))
Pass affine= to skip the affine step.
Modules
| module | contents |
|---|---|
registration |
TorchReg, TorchRegParams, NMI / LNCC / SSD, bending energy, linear elasticity |
result |
RegistrationResult and the Registration protocol |
space |
ImageSpace: grid shape plus voxel → world affine |
bspline |
cubic B-spline control grids: to_dense, from_dense, evaluate |
flow |
SVF exponential (scaling and squaring), compose, integrate, invert |
grid |
identity grids, warp, warp_labels, sample_at, point warping |
jacobian |
Jacobian matrices, determinants, jacobian_stats |
preprocess |
reorientation, resampling between grids, percentile normalisation, N4, masks |
filters |
separable Gaussian smoothing |
io |
NIfTI load/save ([io] extra) |
Conventions: fields are (B, D, *spatial) in voxel units. Voxel axis i is array axis i, as in
a NIfTI sform. A displacement u stands for the map id + u.
Tests
uv run pytest
PyPI
https://pypi.org/project/pyNiftiReg/
License
See LICENSE for details.
Metadata
Release files for pyniftireg 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| pyniftireg-0.1.1.tar.gz | 123.5 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pyniftireg-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 156.6 kB
Release files / pyniftireg-0.1.1.tar.gz
| Download URL | pyniftireg-0.1.1.tar.gz |
|---|---|
| Size | 123.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
02be07d8256cf40f0fb5ebf41ac039ae8ec58b0b1ba20fe1a642d756d2730e1b
|
|
BLAKE2b-256 checksum How to use checksums |
2c6db6ea626410ae833bf9e6e33dadca73ae9643c0124ea02b1500461be36dbc
|
| 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 Oct 12, 2026.
Transparency logRelease files / pyniftireg-0.1.1-py3-none-any.whl
| Download URL | pyniftireg-0.1.1-py3-none-any.whl |
|---|---|
| Size | 33.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1211d0de227a2fd68a5e2f18ad6fabe58e317f5145953d210175e48df82afb30
|
|
BLAKE2b-256 checksum How to use checksums |
14fbadd96d13f2432d6ee7c59add2ed5b8022d9c5ff84b235cd1a0d23e7741b1
|
| 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 Oct 12, 2026.
Transparency logSecurity for pyniftireg 0.1.1
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.
Attestation for pyniftireg-0.1.1.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 12, 2026.
Transparency logA 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.