pub struct RigidTransform {
pub matrix: [f64; 16],
pub params: [f64; 6],
pub fixed_dims: (usize, usize, usize),
pub fixed_affine: [f64; 16],
pub moving_dims: (usize, usize, usize),
pub moving_affine: [f64; 16],
pub ncc: f64,
pub overlap: f64,
pub evaluations: usize,
}Expand description
A recovered rigid transform, together with everything needed to use it.
§Which way it points
Self::matrix maps fixed world → moving world: it answers “where in the moving
acquisition is the anatomy that the fixed volume has here”, which is the direction resampling
needs (for each output voxel, find where to read). The inverse direction is one
Self::inverse away, and it is worth being pedantic about this: applying the rotation the
wrong way round produces a plausible-looking, wrong susceptibility map rather than an error.
Fields§
§matrix: [f64; 16]Row-major 4×4 rigid transform, fixed world → moving world. Pure rotation plus translation; no scaling or shear.
params: [f64; 6]The six parameters matrix was built from: [rx, ry, rz, tx, ty, tz], rotations in
radians composed as Rz(rz)·Ry(ry)·Rx(rx) about the fixed volume’s world centre,
translations in mm of world space.
fixed_dims: (usize, usize, usize)Dimensions and voxel→world affine of the fixed volume — the common grid.
fixed_affine: [f64; 16]§moving_dims: (usize, usize, usize)Dimensions and original voxel→world affine of the moving volume, as handed in.
moving_affine: [f64; 16]§ncc: f64Normalised cross-correlation at the solution, on [-1, 1]. Same-subject magnitude
volumes that genuinely align land above ~0.9; below ~0.5 something is wrong.
overlap: f64Fraction of sampled fixed voxels that found a moving sample at the solution. Well under 1.0 means the volumes only partially overlap, which may be correct (a slab inside a head) or may mean the search wandered.
evaluations: usizeMetric evaluations used, summed over pyramid levels. Diagnostic.
Implementations§
Source§impl RigidTransform
impl RigidTransform
Sourcepub fn identity(
fixed_dims: (usize, usize, usize),
fixed_affine: &[f64; 16],
moving_dims: (usize, usize, usize),
moving_affine: &[f64; 16],
) -> Self
pub fn identity( fixed_dims: (usize, usize, usize), fixed_affine: &[f64; 16], moving_dims: (usize, usize, usize), moving_affine: &[f64; 16], ) -> Self
The identity transform between two grids — the “already registered” answer, for callers that skip estimation but still want one uniform type to resample and read directions through.
Sourcepub fn rotation_degrees(&self) -> [f64; 3]
pub fn rotation_degrees(&self) -> [f64; 3]
The three rotation angles in degrees, in the order Self::params stores them.
Sourcepub fn translation_mm(&self) -> [f64; 3]
pub fn translation_mm(&self) -> [f64; 3]
The translation in mm of world space.
Sourcepub fn rotation_magnitude_deg(&self) -> f64
pub fn rotation_magnitude_deg(&self) -> f64
Total rotation angle in degrees, regardless of axis — the single number to eyeball when deciding whether a registration did anything.
Sourcepub fn aligned_affine(&self) -> [f64; 16]
pub fn aligned_affine(&self) -> [f64; 16]
The moving volume’s voxel→world affine after alignment: re-tag the moving volume with this and its world coordinates agree with the fixed volume’s anatomy, with no interpolation at all.
Do not then read B0 off it. This affine describes the volume in the reference
anatomy’s world, where “world +z” is the reference orientation’s B0 and not this
orientation’s, so b0_direction_from_affine applied to it is meaningless. Use
Self::b0_direction_in_fixed.
Sourcepub fn b0_direction_in_fixed(
&self,
declared_moving_b0: Option<(f64, f64, f64)>,
) -> (f64, f64, f64)
pub fn b0_direction_in_fixed( &self, declared_moving_b0: Option<(f64, f64, f64)>, ) -> (f64, f64, f64)
The moving acquisition’s B0 direction expressed in the fixed grid’s voxel frame —
exactly the bdirs entry [crate::inversion::cosmos] and [crate::inversion::sti] want
for this orientation.
declared_moving_b0 is a sidecar-declared B0 direction in the moving volume’s own voxel
frame, in the convention b0_direction_from_affine returns (the world B0 resolved onto
the volume’s normalised voxel axes). Pass None to read it off the moving affine, which is
right whenever that affine is the scanner’s own.
The chain is: lift the direction into the moving volume’s world, rotate it into the fixed
volume’s world with the inverse of Self::matrix (a free vector carries no translation),
then resolve it onto the fixed grid’s normalised voxel axes. With no rotation it reduces to
b0_direction_from_affine(fixed_affine), as it must.
Sourcepub fn resample(&self, moving: &[f64]) -> Option<Vec<f64>>
pub fn resample(&self, moving: &[f64]) -> Option<Vec<f64>>
Resample continuous moving data (magnitude, an unwrapped field map, χ) onto the fixed
grid. Not for wrapped phase — use Self::resample_complex.
Sourcepub fn resample_mask(&self, mask: &[u8]) -> Option<Vec<u8>>
pub fn resample_mask(&self, mask: &[u8]) -> Option<Vec<u8>>
Resample a moving binary mask or label volume onto the fixed grid (nearest neighbour).
Sourcepub fn resample_complex(
&self,
magnitude: &[f64],
phase: &[f64],
) -> Option<(Vec<f64>, Vec<f64>)>
pub fn resample_complex( &self, magnitude: &[f64], phase: &[f64], ) -> Option<(Vec<f64>, Vec<f64>)>
Resample magnitude and wrapped phase onto the fixed grid together, interpolating
mag·e^{iφ} so the wraps survive. Returns (magnitude, phase).
Sourcepub fn inverse(&self) -> Self
pub fn inverse(&self) -> Self
The same alignment with the roles swapped: the transform taking the old moving volume as fixed and vice versa. Lets a chain of pairwise registrations be re-referenced without re-estimating anything — what intra-run motion correction needs when the volume it registered against is not the one it wants to output on.
Trait Implementations§
Source§impl Clone for RigidTransform
impl Clone for RigidTransform
Source§fn clone(&self) -> RigidTransform
fn clone(&self) -> RigidTransform
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreAuto Trait Implementations§
impl Freeze for RigidTransform
impl RefUnwindSafe for RigidTransform
impl Send for RigidTransform
impl Sync for RigidTransform
impl Unpin for RigidTransform
impl UnsafeUnpin for RigidTransform
impl UnwindSafe for RigidTransform
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<T> CloneAny for T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.§impl<T> DowncastSend for T
impl<T> DowncastSend for T
§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more