pub struct EchoQuality {
pub downweighted_fraction: Vec<f64>,
pub rejected_fraction: Vec<f64>,
pub median_weight: Vec<f64>,
pub median_abs_residual_rad: Vec<f64>,
pub outlier_score: Vec<f64>,
pub voxels_examined: usize,
pub flagged: Vec<usize>,
}Expand description
Per-echo evidence that an echo did not fit the model the others agree on.
Read Self::voxels_examined before trusting a clean report: every statistic here is taken
over the mask, so a mask that selects nothing yields a perfect bill of health.
The per-echo fields are one value per echo, in input order. These are diagnostics: the robust fit has already acted on the per-voxel weights these summarise, and nothing here drops an echo or changes a field map. Deciding to re-acquire, exclude an echo and refit, or accept the map is the caller’s.
Fields§
§downweighted_fraction: Vec<f64>Fraction of in-mask voxels where this echo’s robust weight fell below
RobustFitParams::downweight_level.
The headline number. A clean echo sits near the rate the loss produces on pure noise (a few per cent for Huber at the default tuning); a corrupted one is far above it. Read it relative to the other echoes in the same series, not against an absolute threshold — the baseline moves with SNR, echo count and how much real signal departs from a straight line.
rejected_fraction: Vec<f64>Fraction of in-mask voxels where the weight reached exactly zero. Always 0 for
RobustLoss::Huber, which never rejects; the number that matters for
RobustLoss::Tukey, where it is the fraction of the volume that echo contributed
nothing to.
median_weight: Vec<f64>Median robust weight over the mask. 1.0 means untouched.
median_abs_residual_rad: Vec<f64>Median absolute residual over the mask, in radians, at the final fit. Unlike the fractions above this is a physical quantity, so it is comparable between runs.
outlier_score: Vec<f64>The quantity flagging is decided on: this echo’s 90th-percentile magnitude-weighted absolute residual at the final fit.
Two choices in that sentence, both of which were measured rather than assumed.
At the final fit, because by then a rejected echo carries almost no weight, so its residual is close to what it would be had the model been fitted without it. An in-fit residual shrinks toward zero for whichever echo is pulling the fit hardest, which is precisely the echo you are trying to catch.
90th percentile rather than the median, because corruption need not cover the volume. An echo wrong over a third of the brain still has a perfectly ordinary median, since its median sits in the two thirds that are fine, and the corrupted echo then scores barely more than its neighbours. A high quantile reaches into the affected part while still ignoring the handful of voxels any echo has trouble with. Swapping this back to a median is caught by the tests, which is the cheapest way to see what it is buying.
voxels_examined: usizeHow many voxels were actually examined — the size of the mask this was run over.
Present so that “nothing was flagged” can be told apart from “nothing was looked at”.
Every other field here is a statistic over the mask, so an empty mask produces a
flawless report: no echo flagged, no voxel downweighted, every score zero. That is the
shape of result a failed brain extraction upstream produces, and it is indistinguishable
from a clean series unless something says how much was weighed. Check this before
believing a clean report; 0 means the report is vacuous, not good.
flagged: Vec<usize>Echoes the series’ own spread of Self::outlier_score says are out of line.
Empty unless the worst score exceeds the best by RobustFitParams::flag_ratio; when it
does, this names the worst echo and any other scoring within 80% of it, so a series with
two genuinely bad echoes reports both. Nothing is dropped and no field map changes as a
result — see the type-level note on these being diagnostics.
Implementations§
Source§impl EchoQuality
impl EchoQuality
Trait Implementations§
Source§impl Clone for EchoQuality
impl Clone for EchoQuality
Source§fn clone(&self) -> EchoQuality
fn clone(&self) -> EchoQuality
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 EchoQuality
impl RefUnwindSafe for EchoQuality
impl Send for EchoQuality
impl Sync for EchoQuality
impl Unpin for EchoQuality
impl UnsafeUnpin for EchoQuality
impl UnwindSafe for EchoQuality
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