Skip to main content

estimate_motion

Function estimate_motion 

Source
pub fn estimate_motion(
    series: &[SeriesVolume<'_>],
    mask: Option<&[u8]>,
    params: &MotionParams,
) -> Option<MotionSeries>
Expand description

Estimate where every volume of a series was, relative to a reference volume.

mask is optional and lives on the reference volume’s grid. Passing a brain mask is worth it twice over: it keeps air, neck and the receive-field falloff out of the correlation, and it is the domain VolumeMotion::max_displacement_mm is measured over.

Returns None if the series is empty, if MotionParams::reference does not name a volume, if any volume’s data length disagrees with its dimensions, if the mask length disagrees with the reference volume, or if any pairwise registration could not be evaluated at all. A per-volume failure fails the whole call rather than quietly substituting the identity, because an identity transform for a volume that moved is indistinguishable downstream from a volume that did not move.

§Echoes are harder than repeats

Repeats and runs are the easy case: same contrast, and NCC absorbs the gain difference between them. Echoes are not — T2* decay changes contrast spatially, far more in iron-rich grey matter and vein than in white matter, so a late echo is not a scaled copy of the first one. NCC still finds the alignment, because the anatomy’s edges stay where they are, but its value falls: on the four-echo 7 T phantom, echoes at TE 12, 20 and 28 ms registered to a 4 ms reference scored 0.84, 0.68 and 0.55 while recovering a known 2.5-7.5 degree rotation to 0.04 degrees. A low NCC on an echo series is therefore the contrast and not a failure; MotionParams::min_ncc is defaulted for that case and should be raised for repeats. The same caveat applies, for the same reason, to receive-field shading that rotates with the coil rather than the head — see crate::registration on what NCC does and does not absorb.