pub enum RobustLoss {
Tukey,
Huber,
}Expand description
How a standardised residual becomes a weight.
Measured on the four-echo 7 T phantom, one echo given a slab dropout plus a phase scramble. “Clean-series cost” is how far the robust fit moves the field map when there is nothing wrong — the price of insurance; “corrupted-series error” is how far the field map sits from the clean answer when there is. Both are relative errors against the plain magnitude-weighted fit of the clean data.
| clean-series cost | corrupted-series error | flagged the right echo | |
|---|---|---|---|
| no robust fit at all | 0 by definition | 0.0424 | — |
Huber at c = 1.345 | 0.0142 | 0.0304 | yes |
Tukey at c = 4.685 | 0.0059 | 0.0268 | yes |
| Tukey with the degeneracy guard removed | — | 0.320 | yes |
The last row is why multi_echo_robust_fit has that guard, and the reason the obvious
a-priori argument — that a rejecting loss must be wrong for a four-echo train, because
throwing an echo away leaves three points to fit two parameters — is only half right. It is
exactly right about the danger and wrong about the remedy: the fix is to stop the fit
becoming under-determined, not to stop rejecting.
Variants§
Tukey
w = (1 - u²)² inside the tuning radius and zero outside: an outlier past the radius
is discarded entirely. Conventional tuning constant 4.685.
The default, on the evidence above — it both protects a corrupted series better and disturbs a clean one less, because it leaves everything inside the radius at full weight instead of shading the whole distribution the way Huber’s tail does.
Huber
w = 1 inside the tuning radius, w = c/|u| outside: an outlier’s influence is capped
but never removed. Conventional tuning constant 1.345.
Never rejects, so EchoQuality::rejected_fraction is always zero and the fit can never
become under-determined no matter how the data behaves. Worth choosing when that
guarantee is worth more than the accuracy, or on a series short enough that the guard
would be firing constantly.
Implementations§
Source§impl RobustLoss
impl RobustLoss
Sourcepub fn conventional_tuning(self) -> f64
pub fn conventional_tuning(self) -> f64
The conventional tuning constant for this loss — Tukey 4.685, Huber 1.345, both the
values that give 95% efficiency against purely Gaussian noise.
Used when RobustFitParams::tuning is None. On the phantom above these are also
where the corrupted-series error bottoms out, so there is no tension between the textbook
choice and the measured one: for Tukey the sweep gave 0.0397 / 0.0341 / 0.0268 /
0.0289 / 0.0361 at c = 2.5 / 3.5 / 4.685 / 6 / 8.
Trait Implementations§
Source§impl Clone for RobustLoss
impl Clone for RobustLoss
Source§fn clone(&self) -> RobustLoss
fn clone(&self) -> RobustLoss
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreimpl Copy for RobustLoss
Source§impl Debug for RobustLoss
impl Debug for RobustLoss
Source§impl Default for RobustLoss
impl Default for RobustLoss
Source§fn default() -> RobustLoss
fn default() -> RobustLoss
impl Eq for RobustLoss
Source§impl PartialEq for RobustLoss
impl PartialEq for RobustLoss
Source§impl Serialize for RobustLoss
impl Serialize for RobustLoss
impl StructuralPartialEq for RobustLoss
Auto Trait Implementations§
impl Freeze for RobustLoss
impl RefUnwindSafe for RobustLoss
impl Send for RobustLoss
impl Sync for RobustLoss
impl Unpin for RobustLoss
impl UnsafeUnpin for RobustLoss
impl UnwindSafe for RobustLoss
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
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.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