pub struct RigidParams {
pub levels: usize,
pub max_samples: usize,
pub max_iterations: usize,
pub max_evaluations: usize,
pub tolerance: f64,
pub rotation_step_deg: f64,
pub translation_step_mm: f64,
pub min_overlap: f64,
pub initial: Option<[f64; 6]>,
}Expand description
Registration parameters.
Fields§
§levels: usizePyramid levels, finest included. 5 means the volume is registered at 1/16, then 1/8,
1/4, 1/2 and full resolution. Levels that would shrink any axis below 8 voxels are
dropped, so a small volume quietly gets fewer and nothing has to be tuned for it.
This is the capture range, and it is the one parameter not to lower. The search starts
from the identity, so for identically prescribed slabs it begins with the whole head
rotation as the error to find — and 1 - NCC is not a single bowl. A brain is roughly
symmetric and full of repeating structure, so the cost falls, rises as one gyrus lines up
with its neighbour, and falls again; past some misalignment the coarsest level has a
competing minimum of its own and the search converges into it, reporting success.
Measured on the in-vivo-sized test phantom
(test_multiorient_register_capture_range), sweeping an oblique-axis rotation:
| levels | converges up to |
|---|---|
| 3 | 40°, then fails hard — 92° out, NCC 0.19 |
| 5 | the whole swept range to 70°, to 0.01° |
3 was the original default and is not enough: STI wants orientations spread widely over the sphere, so 45° of repositioning is ordinary and would have landed in the failure. The two extra levels cost about twice the metric evaluations but very little wall clock, because the coarse levels hold a few thousand samples each against the cap below.
max_samples: usizeUpper bound on fixed voxels sampled per metric evaluation, per level.
This, not the volume size, sets the cost of a registration: a 256³ and a 700³ volume take the same time. 6 parameters are vastly over-determined by 10⁵ samples, so lowering this buys speed long before it costs accuracy.
max_iterations: usizeMaximum Powell cycles (one pass over all six directions) per level.
max_evaluations: usizeTotal metric evaluations across all levels, as a hard stop. Reached only on a cost surface that will not converge; the best parameters so far are returned either way.
tolerance: f64Relative cost improvement per Powell cycle below which a level is considered converged.
rotation_step_deg: f64Initial line-search step for the three rotations, at the finest level, in degrees. Coarser levels scale it up with the level’s decimation factor.
translation_step_mm: f64Initial line-search step for the three translations, at the finest level, in mm. Coarser levels scale it up with the level’s decimation factor.
min_overlap: f64Smallest fraction of sampled fixed voxels that must still land inside the moving volume.
NCC over a shrinking overlap is gameable — slide the volumes apart until only one well-correlated patch is left and the correlation goes up. Candidates below this floor are costed worse than any real match, with a gradient that pushes back into the valid region. Keep it low enough for a legitimately partial overlap (a thin slab against a whole head).
initial: Option<[f64; 6]>Starting parameters, in the convention of RigidTransform::params. None starts from
the identity, i.e. it trusts the two affines to place the volumes in a common world —
correct both for separately prescribed slabs (where the affines differ and are truthful)
and for identically prescribed ones (where they agree and only the anatomy moved).
Seed it when a previous answer is a good prior and the pyramid’s coarse search is wasted work: registering a time series to one reference, for instance, where each volume starts from where the last one landed. The parameters are defined about the fixed volume’s world centre, so they carry between pairs that share a fixed volume without conversion.
Trait Implementations§
Source§impl Clone for RigidParams
impl Clone for RigidParams
Source§fn clone(&self) -> RigidParams
fn clone(&self) -> RigidParams
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for RigidParams
impl Debug for RigidParams
Source§impl Default for RigidParams
impl Default for RigidParams
Auto Trait Implementations§
impl Freeze for RigidParams
impl RefUnwindSafe for RigidParams
impl Send for RigidParams
impl Sync for RigidParams
impl Unpin for RigidParams
impl UnsafeUnpin for RigidParams
impl UnwindSafe for RigidParams
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