pub struct SfsBase<S: Shape, N: Normalisation> { /* private fields */ }
Expand description
An multi-dimensional site frequency spectrum (“SFS”).
Elements are stored in row-major order: the last index varies the fastest.
The number of dimensions of the SFS may either be known at compile-time or run-time,
and this is governed by the Shape
trait. Moreover, the SFS may or may not be normalised
to probability scale, and this is controlled by the Normalisation
trait.
See also the Sfs
, USfs
, DynSfs
, and DynUSfs
type aliases.
Implementations§
Source§impl<const D: usize> SfsBase<[usize; D], Norm>
impl<const D: usize> SfsBase<[usize; D], Norm>
Sourcepub fn e_step<I>(self, input: I) -> (SumOf<LogLikelihood>, USfs<D>)
pub fn e_step<I>(self, input: I) -> (SumOf<LogLikelihood>, USfs<D>)
Returns the log-likelihood of the data given the SFS, and the expected number of sites in each frequency bin given the SFS and the input.
This corresponds to an E-step for the EM algorithm. The returned SFS corresponds to the
expected number of sites in each bin given self
and the input
.
The sum of the returned SFS will be equal to the number of sites in the input.
§Panics
Panics if any of the sites in the input does not fit the shape of self
.
§Examples
use winsfs_core::{sfs::Sfs, saf1d, sfs1d};
let sfs = Sfs::uniform([5]);
let saf = saf1d![
[1., 0., 0., 0., 0.],
[0., 1., 0., 0., 0.],
[1., 0., 0., 0., 0.],
[0., 0., 0., 1., 0.],
];
let (log_likelihood, posterior) = sfs.clone().e_step(&saf);
assert_eq!(posterior, sfs1d![2., 1., 0., 1., 0.]);
assert_eq!(log_likelihood, sfs.log_likelihood(&saf));
Sourcepub fn par_e_step<I>(self, input: I) -> (SumOf<LogLikelihood>, USfs<D>)
pub fn par_e_step<I>(self, input: I) -> (SumOf<LogLikelihood>, USfs<D>)
Returns the log-likelihood of the data given the SFS, and the expected number of sites in each frequency bin given the SFS and the input.
This is the parallel version of Sfs::e_step
, see also its documentation for more.
§Panics
Panics if any of the sites in the input does not fit the shape of self
.
§Examples
use winsfs_core::{sfs::Sfs, saf1d, sfs1d};
let sfs = Sfs::uniform([5]);
let saf = saf1d![
[1., 0., 0., 0., 0.],
[0., 1., 0., 0., 0.],
[1., 0., 0., 0., 0.],
[0., 0., 0., 1., 0.],
];
let (log_likelihood, posterior) = sfs.clone().par_e_step(&saf);
assert_eq!(posterior, sfs1d![2., 1., 0., 1., 0.]);
assert_eq!(log_likelihood, sfs.log_likelihood(&saf));
Sourcepub fn log_likelihood<I>(self, input: I) -> SumOf<LogLikelihood>where
I: IntoSiteIterator<D>,
pub fn log_likelihood<I>(self, input: I) -> SumOf<LogLikelihood>where
I: IntoSiteIterator<D>,
Returns the log-likelihood of the data given the SFS.
§Panics
Panics if any of the sites in the input does not fit the shape of self
.
§Examples
use winsfs_core::{em::likelihood::{Likelihood, SumOf}, sfs::Sfs, saf1d, sfs1d};
let sfs = Sfs::uniform([5]);
let saf = saf1d![
[1., 0., 0., 0., 0.],
[0., 1., 0., 0., 0.],
[1., 0., 0., 0., 0.],
[0., 0., 0., 1., 0.],
];
let expected = SumOf::new(Likelihood::from(0.2f64.powi(4)).ln(), saf.sites());
assert_eq!(sfs.log_likelihood(&saf), expected);
Sourcepub fn par_log_likelihood<I>(self, input: I) -> SumOf<LogLikelihood>where
I: IntoParallelSiteIterator<D>,
pub fn par_log_likelihood<I>(self, input: I) -> SumOf<LogLikelihood>where
I: IntoParallelSiteIterator<D>,
Returns the log-likelihood of the data given the SFS.
This is the parallel version of Sfs::log_likelihood
.
§Panics
Panics if any of the sites in the input does not fit the shape of self
.
§Examples
use winsfs_core::{em::likelihood::{Likelihood, SumOf}, sfs::Sfs, saf1d, sfs1d};
let sfs = Sfs::uniform([5]);
let saf = saf1d![
[1., 0., 0., 0., 0.],
[0., 1., 0., 0., 0.],
[1., 0., 0., 0., 0.],
[0., 0., 0., 1., 0.],
];
let expected = SumOf::new(Likelihood::from(0.2f64.powi(4)).ln(), saf.sites());
assert_eq!(sfs.par_log_likelihood(&saf), expected);
Sourcepub fn stream_e_step<R>(
self,
reader: R,
) -> Result<(SumOf<LogLikelihood>, USfs<D>)>
pub fn stream_e_step<R>( self, reader: R, ) -> Result<(SumOf<LogLikelihood>, USfs<D>)>
Returns the log-likelihood of the data given the SFS, and the expected number of sites in each frequency bin given the SFS and the input.
This is the streaming version of Sfs::e_step
, see also its documentation for more.
§Panics
Panics if any of the sites in the input does not fit the shape of self
.
Sourcepub fn stream_log_likelihood<R>(self, reader: R) -> Result<SumOf<LogLikelihood>>
pub fn stream_log_likelihood<R>(self, reader: R) -> Result<SumOf<LogLikelihood>>
Returns the log-likelihood of the data given the SFS.
This is the streaming version of Sfs::log_likelihood
.
§Panics
Panics if any of the sites in the input does not fit the shape of self
.
Source§impl<S: Shape, N: Normalisation> SfsBase<S, N>
impl<S: Shape, N: Normalisation> SfsBase<S, N>
Sourcepub fn as_slice(&self) -> &[f64]
pub fn as_slice(&self) -> &[f64]
Returns the values of the SFS as a flat, row-major slice.
§Examples
use winsfs_core::sfs2d;
let sfs = sfs2d![
[0., 1., 2.],
[3., 4., 5.],
];
assert_eq!(sfs.as_slice(), [0., 1., 2., 3., 4., 5.]);
Sourcepub fn fold(&self) -> Self
pub fn fold(&self) -> Self
Returns a folded version of the SFS.
Folding is useful when the spectrum has not been properly polarised, so that there is no meaningful distinction between having 0 and 2N (in the diploid case) variants at a site. The folding operation collapses these indistinguishable bins by adding the value from the lower part of the spectrum onto the upper, and setting the lower value to zero.
Note that we adopt the convention that on the “diagonal” of the SFS, where there is less of a convention on what is the correct way of folding, the arithmetic mean of the candidates is used. The examples below illustrate this.
§Examples
Folding in 1D:
use winsfs_core::sfs1d;
let sfs = sfs1d![5., 2., 3., 10., 1.];
assert_eq!(sfs.fold(), sfs1d![6., 12., 3., 0., 0.]);
Folding in 2D (square input):
use winsfs_core::sfs2d;
let sfs = sfs2d![
[4., 2., 10.],
[0., 3., 4.],
[7., 2., 1.],
];
let expected = sfs2d![
[5., 4., 8.5],
[4., 3., 0.],
[8.5, 0., 0.],
];
assert_eq!(sfs.fold(), expected);
Folding in 2D (non-square input):
use winsfs_core::sfs2d;
let sfs = sfs2d![
[4., 2., 10.],
[0., 3., 4.],
];
let expected = sfs2d![
[8., 5., 0.],
[10., 0., 0.],
];
assert_eq!(sfs.fold(), expected);
Sourcepub fn format_flat(&self, sep: &str, precision: usize) -> String
pub fn format_flat(&self, sep: &str, precision: usize) -> String
Returns a string containing a flat, row-major represention of the SFS.
§Examples
use winsfs_core::sfs1d;
let sfs = sfs1d![0.0, 0.1, 0.2];
assert_eq!(sfs.format_flat(" ", 1), "0.0 0.1 0.2");
use winsfs_core::sfs2d;
let sfs = sfs2d![[0.01, 0.12], [0.23, 0.34]];
assert_eq!(sfs.format_flat(",", 2), "0.01,0.12,0.23,0.34");
Sourcepub fn get(&self, index: &S) -> Option<&f64>
pub fn get(&self, index: &S) -> Option<&f64>
Returns a value at an index in the SFS.
If the index is out of bounds, None
is returned.
§Examples
use winsfs_core::sfs1d;
let sfs = sfs1d![0.0, 0.1, 0.2];
assert_eq!(sfs.get(&[0]), Some(&0.0));
assert_eq!(sfs.get(&[1]), Some(&0.1));
assert_eq!(sfs.get(&[2]), Some(&0.2));
assert_eq!(sfs.get(&[3]), None);
use winsfs_core::sfs2d;
let sfs = sfs2d![[0.0, 0.1, 0.2], [0.3, 0.4, 0.5], [0.6, 0.7, 0.8]];
assert_eq!(sfs.get(&[0, 0]), Some(&0.0));
assert_eq!(sfs.get(&[1, 2]), Some(&0.5));
assert_eq!(sfs.get(&[3, 0]), None);
Sourcepub fn into_normalised(self) -> Result<SfsBase<S, Norm>, NormError>
pub fn into_normalised(self) -> Result<SfsBase<S, Norm>, NormError>
Returns a normalised SFS, consuming self
.
This works purely on the type level, and does not modify the actual values in the SFS.
If the SFS is not already normalised, an error is returned. To modify the SFS to become
normalised, see Sfs::normalise
.
§Examples
An unnormalised SFS with values summing to one can be turned into a normalised SFS:
use winsfs_core::{sfs1d, sfs::{Sfs, USfs}};
let sfs: USfs<1> = sfs1d![0.2; 5];
let sfs: Sfs<1> = sfs.into_normalised().unwrap();
Otherwise, an unnormalised SFS cannot be normalised SFS using this method:
use winsfs_core::{sfs1d, sfs::USfs};
let sfs: USfs<1> = sfs1d![2.; 5];
assert!(sfs.into_normalised().is_err());
Use Sfs::normalise
instead.
Sourcepub fn into_unnormalised(self) -> SfsBase<S, Unnorm>
pub fn into_unnormalised(self) -> SfsBase<S, Unnorm>
Returns an unnormalised SFS, consuming self
.
This works purely on the type level, and does not modify the actual values in the SFS.
§Examples
use winsfs_core::sfs::{Sfs, USfs};
let sfs: Sfs<1> = Sfs::uniform([7]);
let sfs: USfs<1> = sfs.into_unnormalised();
Sourcepub fn iter(&self) -> Iter<'_, f64>
pub fn iter(&self) -> Iter<'_, f64>
Returns an iterator over the elements in the SFS in row-major order.
§Examples
use winsfs_core::sfs2d;
let sfs = sfs2d![
[0., 1., 2.],
[3., 4., 5.],
[6., 7., 8.],
];
let expected = (0..9).map(|x| x as f64);
assert!(sfs.iter().zip(expected).all(|(&x, y)| x == y));
Source§impl<const D: usize, N: Normalisation> SfsBase<ConstShape<D>, N>
impl<const D: usize, N: Normalisation> SfsBase<ConstShape<D>, N>
Sourcepub fn frequencies(&self) -> impl Iterator<Item = [f64; D]>
pub fn frequencies(&self) -> impl Iterator<Item = [f64; D]>
Returns an iterator over the sample frequencies of the SFS in row-major order.
Note that this is not the contents of SFS, but the frequencies corresponding
to the indices. See Sfs::iter
for an iterator over the SFS values themselves.
§Examples
use winsfs_core::sfs::Sfs;
let sfs = Sfs::uniform([2, 3]);
let mut iter = sfs.frequencies();
assert_eq!(iter.next(), Some([0., 0.]));
assert_eq!(iter.next(), Some([0., 0.5]));
assert_eq!(iter.next(), Some([0., 1.]));
assert_eq!(iter.next(), Some([1., 0.]));
assert_eq!(iter.next(), Some([1., 0.5]));
assert_eq!(iter.next(), Some([1., 1.]));
assert!(iter.next().is_none());
Sourcepub fn indices(&self) -> Indices<ConstShape<D>> ⓘ
pub fn indices(&self) -> Indices<ConstShape<D>> ⓘ
Returns an iterator over the indices in the SFS in row-major order.
§Examples
use winsfs_core::sfs::Sfs;
let sfs = Sfs::uniform([2, 3]);
let mut iter = sfs.indices();
assert_eq!(iter.next(), Some([0, 0]));
assert_eq!(iter.next(), Some([0, 1]));
assert_eq!(iter.next(), Some([0, 2]));
assert_eq!(iter.next(), Some([1, 0]));
assert_eq!(iter.next(), Some([1, 1]));
assert_eq!(iter.next(), Some([1, 2]));
assert!(iter.next().is_none());
Source§impl<S: Shape> SfsBase<S, Unnorm>
impl<S: Shape> SfsBase<S, Unnorm>
Sourcepub fn as_mut_slice(&mut self) -> &mut [f64]
pub fn as_mut_slice(&mut self) -> &mut [f64]
Returns the a mutable reference values of the SFS as a flat, row-major slice.
§Examples
use winsfs_core::sfs2d;
let mut sfs = sfs2d![
[0., 1., 2.],
[3., 4., 5.],
];
assert_eq!(sfs.as_slice(), [0., 1., 2., 3., 4., 5.]);
sfs.as_mut_slice()[0] = 100.;
assert_eq!(sfs.as_slice(), [100., 1., 2., 3., 4., 5.]);
Sourcepub fn from_elem(elem: f64, shape: S) -> Self
pub fn from_elem(elem: f64, shape: S) -> Self
Creates a new, unnormalised SFS by repeating a single value.
See also Sfs::uniform
to create a normalised SFS with uniform values.
§Examples
use winsfs_core::sfs::USfs;
let sfs = USfs::from_elem(0.1, [7, 5]);
assert_eq!(sfs.shape(), &[7, 5]);
assert!(sfs.iter().all(|&x| x == 0.1));
Sourcepub fn from_iter_shape<I>(iter: I, shape: S) -> Result<Self, ShapeError<S>>where
I: IntoIterator<Item = f64>,
pub fn from_iter_shape<I>(iter: I, shape: S) -> Result<Self, ShapeError<S>>where
I: IntoIterator<Item = f64>,
Creates a new, unnormalised SFS from an iterator.
§Examples
use winsfs_core::sfs::USfs;
let iter = (0..9).map(|x| x as f64);
let sfs = USfs::from_iter_shape(iter, [3, 3]).expect("shape didn't fit iterator!");
assert_eq!(sfs[[1, 2]], 5.0);
Sourcepub fn from_vec_shape(vec: Vec<f64>, shape: S) -> Result<Self, ShapeError<S>>
pub fn from_vec_shape(vec: Vec<f64>, shape: S) -> Result<Self, ShapeError<S>>
Creates a new, unnormalised SFS from a vector.
§Examples
use winsfs_core::sfs::USfs;
let vec: Vec<f64> = (0..9).map(|x| x as f64).collect();
let sfs = USfs::from_vec_shape(vec, [3, 3]).expect("shape didn't fit vector!");
assert_eq!(sfs[[2, 0]], 6.0);
Sourcepub fn get_mut(&mut self, index: &S) -> Option<&mut f64>
pub fn get_mut(&mut self, index: &S) -> Option<&mut f64>
Returns a mutable reference to a value at an index in the SFS.
If the index is out of bounds, None
is returned.
§Examples
use winsfs_core::sfs1d;
let mut sfs = sfs1d![0.0, 0.1, 0.2];
assert_eq!(sfs[[0]], 0.0);
if let Some(v) = sfs.get_mut(&[0]) {
*v = 0.5;
}
assert_eq!(sfs[[0]], 0.5);
use winsfs_core::sfs2d;
let mut sfs = sfs2d![[0.0, 0.1, 0.2], [0.3, 0.4, 0.5], [0.6, 0.7, 0.8]];
assert_eq!(sfs[[0, 0]], 0.0);
if let Some(v) = sfs.get_mut(&[0, 0]) {
*v = 0.5;
}
assert_eq!(sfs[[0, 0]], 0.5);
Sourcepub fn iter_mut(&mut self) -> IterMut<'_, f64>
pub fn iter_mut(&mut self) -> IterMut<'_, f64>
Returns an iterator over mutable references to the elements in the SFS in row-major order.
Sourcepub fn normalise(self) -> SfsBase<S, Norm>
pub fn normalise(self) -> SfsBase<S, Norm>
Returns a normalised SFS, consuming self
.
The values in the SFS are modified to sum to one.
§Examples
use winsfs_core::{sfs1d, sfs::{Sfs, USfs}};
let sfs: USfs<1> = sfs1d![0., 1., 2., 3., 4.];
let sfs: Sfs<1> = sfs.normalise();
assert_eq!(sfs[[1]], 0.1);
Source§impl SfsBase<ConstShape<1>, Unnorm>
impl SfsBase<ConstShape<1>, Unnorm>
Trait Implementations§
Source§impl<S: Shape, N: Normalisation, M: Normalisation> Add<&SfsBase<S, M>> for SfsBase<S, N>
impl<S: Shape, N: Normalisation, M: Normalisation> Add<&SfsBase<S, M>> for SfsBase<S, N>
Source§impl<S: Shape, N: Normalisation, M: Normalisation> Add<SfsBase<S, M>> for SfsBase<S, N>
impl<S: Shape, N: Normalisation, M: Normalisation> Add<SfsBase<S, M>> for SfsBase<S, N>
Source§impl<S: Shape, N: Normalisation> AddAssign<&SfsBase<S, N>> for SfsBase<S, Unnorm>
impl<S: Shape, N: Normalisation> AddAssign<&SfsBase<S, N>> for SfsBase<S, Unnorm>
Source§fn add_assign(&mut self, rhs: &SfsBase<S, N>)
fn add_assign(&mut self, rhs: &SfsBase<S, N>)
+=
operation. Read moreSource§impl<S: Shape, N: Normalisation> AddAssign<SfsBase<S, N>> for SfsBase<S, Unnorm>
impl<S: Shape, N: Normalisation> AddAssign<SfsBase<S, N>> for SfsBase<S, Unnorm>
Source§fn add_assign(&mut self, rhs: SfsBase<S, N>)
fn add_assign(&mut self, rhs: SfsBase<S, N>)
+=
operation. Read moreSource§impl<const D: usize, N: Normalisation> From<SfsBase<[usize; D], N>> for SfsBase<DynShape, N>
impl<const D: usize, N: Normalisation> From<SfsBase<[usize; D], N>> for SfsBase<DynShape, N>
Source§fn from(sfs: SfsBase<ConstShape<D>, N>) -> Self
fn from(sfs: SfsBase<ConstShape<D>, N>) -> Self
Source§impl<S: Shape, N: Normalisation, M: Normalisation> Sub<&SfsBase<S, M>> for SfsBase<S, N>
impl<S: Shape, N: Normalisation, M: Normalisation> Sub<&SfsBase<S, M>> for SfsBase<S, N>
Source§impl<S: Shape, N: Normalisation, M: Normalisation> Sub<SfsBase<S, M>> for SfsBase<S, N>
impl<S: Shape, N: Normalisation, M: Normalisation> Sub<SfsBase<S, M>> for SfsBase<S, N>
Source§impl<S: Shape, N: Normalisation> SubAssign<&SfsBase<S, N>> for SfsBase<S, Unnorm>
impl<S: Shape, N: Normalisation> SubAssign<&SfsBase<S, N>> for SfsBase<S, Unnorm>
Source§fn sub_assign(&mut self, rhs: &SfsBase<S, N>)
fn sub_assign(&mut self, rhs: &SfsBase<S, N>)
-=
operation. Read moreSource§impl<S: Shape, N: Normalisation> SubAssign<SfsBase<S, N>> for SfsBase<S, Unnorm>
impl<S: Shape, N: Normalisation> SubAssign<SfsBase<S, N>> for SfsBase<S, Unnorm>
Source§fn sub_assign(&mut self, rhs: SfsBase<S, N>)
fn sub_assign(&mut self, rhs: SfsBase<S, N>)
-=
operation. Read moreSource§impl<const D: usize, N: Normalisation> TryFrom<SfsBase<Box<[usize]>, N>> for SfsBase<ConstShape<D>, N>
impl<const D: usize, N: Normalisation> TryFrom<SfsBase<Box<[usize]>, N>> for SfsBase<ConstShape<D>, N>
impl<S: Shape, N: Normalisation> StructuralPartialEq for SfsBase<S, N>
Auto Trait Implementations§
impl<S, N> Freeze for SfsBase<S, N>where
S: Freeze,
impl<S, N> RefUnwindSafe for SfsBase<S, N>where
S: RefUnwindSafe,
N: RefUnwindSafe,
impl<S, N> Send for SfsBase<S, N>
impl<S, N> Sync for SfsBase<S, N>
impl<S, N> Unpin for SfsBase<S, N>
impl<S, N> UnwindSafe for SfsBase<S, N>where
S: UnwindSafe,
N: UnwindSafe,
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
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
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