pub fn b0_direction_from_affine(affine: &[f64; 16]) -> (f64, f64, f64)Expand description
Direction of the scanner’s B0 field (world +z) expressed in voxel coordinates, normalised.
The voxel→world matrix is A = R·S, with R a rotation and S = diag(voxel sizes). Dividing
each column of A by its norm recovers R, whose inverse is its transpose, so the direction
is simply the third row of the normalised matrix. An axial acquisition returns (0, 0, 1).
Factoring the voxel sizes out first is what makes this correct for anisotropic voxels. Using
A⁻¹·(0,0,1) instead — inverting the matrix with the voxel scaling still in it — silently
skews the direction: on a 0.8 × 0.8 × 3 mm acquisition tilted 23° it returns a direction 58°
from z, and the resulting dipole kernel destroys most of the susceptibility contrast. That
was a real regression in QSMxT 8.2.2; [tests::b0_direction_anisotropic_oblique] pins it.