Expand description
Scan geometry derived from the NIfTI affine, and resampling to an axial grid.
Two things QSM needs from the affine and nothing else provides:
- Which way B0 points in voxel space. The dipole kernel is built in the voxel grid, so an
oblique acquisition must either be told the true B0 direction (
b0_direction_from_affine) or be resampled so that the grid is cardinal-aligned and B0 is(0, 0, 1)by construction (resample_complex_to_axial). Getting this wrong rotates the kernel and suppresses susceptibility contrast in exactly the iron-rich structures QSM is usually measuring. - How oblique the acquisition is (
obliquity_from_affine), so a pipeline can decide whether resampling is worth the interpolation.
§Phase must be resampled in the complex domain
Wrapped phase cannot be interpolated directly: halfway between +3.0 and -3.0 rad, a linear
interpolator returns 0.0, when the correct answer is near ±π. Every wrap in the volume
becomes a band of wrong values. resample_complex_to_axial takes magnitude and phase
together, interpolates mag·e^{iφ} as real and imaginary parts, and recovers magnitude and
phase afterwards, which is well defined across wraps. Use resample_to_axial only for
quantities that are already continuous (magnitude, an unwrapped field map, χ).
Structs§
- Axial
Grid - The cardinal-aligned grid an oblique volume resamples onto, plus the mapping back to the
original voxel space. Build once with
axial_grid_forand reuse for every volume that shares the geometry (magnitude, phase, mask), so they land on identical grids. - Axial
Resample Params - Options for
resample_complex_to_axial. - GridMap
- Mapping from one voxel grid to another, each described by its own affine.
- Resampled
Complex - Magnitude and phase resampled together onto a cardinal-aligned grid.
- Resampled
Volume - A volume resampled onto a cardinal-aligned grid.
- Split
Mix64 🔒 - SplitMix64 — small, dependency-free, and adequate for filling empty corners with noise.
Functions§
- axial_
grid_ for - Build the axial grid covering the same world-space extent as an oblique volume, keeping its
voxel sizes. The new affine is diagonal, so
b0_direction_from_affineon it returns(0, 0, 1). - b0_
angle_ from_ affine - Angle (degrees) between B0 and the voxel
+zaxis — the tilt that matters for the dipole kernel. Zero for an axial acquisition; equals the scanner’s slice tilt for a simple oblique. - b0_
direction_ from_ affine - Direction of the scanner’s B0 field (world
+z) expressed in voxel coordinates, normalised. - obliquity_
axes_ from_ affine - Per-axis obliquity (degrees), matching
nibabel.affines.obliquity: for each voxel axis, the angle between it and the closest world axis.[0, 0, 0]for a cardinal-aligned acquisition. - obliquity_
from_ affine - Scalar obliquity (degrees): the Euclidean norm of
obliquity_axes_from_affine. - resample_
complex_ onto - Resample magnitude and wrapped phase from one grid onto another, through the complex domain
so the wraps survive. Returns
(magnitude, phase). - resample_
complex_ to_ axial - Resample magnitude and wrapped phase to a cardinal-aligned grid, interpolating in the complex domain so wraps survive.
- resample_
mask_ onto - Resample a binary mask from one grid onto another (nearest neighbour).
- resample_
mask_ to_ axial - Resample a binary mask to a cardinal-aligned grid with nearest-neighbour interpolation.
- resample_
onto - Resample continuous data (magnitude, an unwrapped field, χ) from one grid onto another.
Returns
Noneif the source affine is singular. - resample_
to_ axial - Resample a continuous volume (magnitude, unwrapped field, χ) to a cardinal-aligned grid.
- seed_
from_ 🔒slice - Deterministic seed from volume contents (FNV-1a over the bit patterns).
- trilinear_
sample 🔒 - Trilinear interpolation at a fractional voxel coordinate, clamped at the edges.
- voxel_
sizes_ from_ affine - Voxel sizes (mm) from a row-major 4×4 affine: the norms of its three columns.
- world_
to_ 🔒voxel - Invert the 3×3 of an affine and fold in its translation, giving world→voxel as a 3×4.