use crate::alignment::phmm::{
InvalidModelError, PhmmError, PhmmNumber,
indexing::{GetLayer, GetLayerMut},
state::PhmmState,
};
use std::ops::{Index, IndexMut};
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
pub struct TransitionParams<T>(pub(crate) [[T; 3]; 3]);
impl<T: Copy> TransitionParams<T> {
#[inline]
#[must_use]
#[allow(dead_code)]
pub fn exiting_params(&self, state: PhmmState) -> [T; 3] {
[
self[(state, PhmmState::Match)],
self[(state, PhmmState::Delete)],
self[(state, PhmmState::Insert)],
]
}
#[inline]
#[must_use]
#[allow(dead_code)]
pub fn entering_params(&self, state: PhmmState) -> [T; 3] {
self[state]
}
#[inline]
#[must_use]
#[cfg(feature = "dev-phmm-regression")]
pub fn as_array(&self) -> &[[T; 3]; 3] {
&self.0
}
#[inline]
#[must_use]
#[cfg(feature = "dev-phmm-regression")]
pub fn from_array(arr: [[T; 3]; 3]) -> Self {
Self(arr)
}
}
impl<T: PhmmNumber> Default for TransitionParams<T> {
#[inline]
fn default() -> Self {
Self([[T::INFINITY; 3]; 3])
}
}
impl<T> Index<(PhmmState, PhmmState)> for TransitionParams<T> {
type Output = T;
#[inline]
fn index(&self, index: (PhmmState, PhmmState)) -> &Self::Output {
&self.0[usize::from(index.1)][usize::from(index.0)]
}
}
impl<T> IndexMut<(PhmmState, PhmmState)> for TransitionParams<T> {
#[inline]
fn index_mut(&mut self, index: (PhmmState, PhmmState)) -> &mut Self::Output {
&mut self.0[usize::from(index.1)][usize::from(index.0)]
}
}
impl<T> Index<PhmmState> for TransitionParams<T> {
type Output = [T; 3];
#[inline]
fn index(&self, index: PhmmState) -> &Self::Output {
&self.0[usize::from(index)]
}
}
impl<T> IndexMut<PhmmState> for TransitionParams<T> {
#[inline]
fn index_mut(&mut self, index: PhmmState) -> &mut Self::Output {
&mut self.0[usize::from(index)]
}
}
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
pub struct EmissionParams<T, const S: usize>([T; S]);
impl<T, const S: usize> EmissionParams<T, S> {
#[inline]
#[must_use]
pub fn from_array(arr: [T; S]) -> Self {
Self(arr)
}
#[inline]
#[must_use]
pub fn as_slice(&self) -> &[T] {
&self.0
}
#[inline]
#[must_use]
pub fn as_array(&self) -> &[T; S] {
&self.0
}
#[inline]
pub fn iter(&self) -> std::slice::Iter<'_, T> {
self.0.iter()
}
}
impl<T: PhmmNumber, const S: usize> EmissionParams<T, S> {
#[inline]
#[must_use]
#[allow(clippy::cast_precision_loss)]
pub fn uniform() -> Self {
Self([T::from_prob(1.0f64 / (S as f64)); S])
}
}
impl<T: PhmmNumber, const S: usize> Default for EmissionParams<T, S> {
#[inline]
fn default() -> Self {
Self([T::INFINITY; S])
}
}
impl<'a, T, const S: usize> IntoIterator for &'a EmissionParams<T, S> {
type Item = &'a T;
type IntoIter = std::slice::Iter<'a, T>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.0.iter()
}
}
impl<T, const S: usize> Index<usize> for EmissionParams<T, S> {
type Output = T;
#[inline]
fn index(&self, index: usize) -> &Self::Output {
&self.0[index]
}
}
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct LayerParams<T, const S: usize> {
pub transition: TransitionParams<T>,
pub emission_match: EmissionParams<T, S>,
pub emission_insert: EmissionParams<T, S>,
}
impl<T: PhmmNumber, const S: usize> Default for LayerParams<T, S> {
#[inline]
fn default() -> Self {
Self {
transition: TransitionParams::default(),
emission_match: EmissionParams::default(),
emission_insert: EmissionParams::default(),
}
}
}
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct CorePhmm<T, const S: usize>(Vec<LayerParams<T, S>>);
impl<T, const S: usize> CorePhmm<T, S> {
#[inline]
#[allow(dead_code)]
pub fn new(layers: Vec<LayerParams<T, S>>) -> Result<Self, PhmmError> {
if layers.len() >= 2 {
Ok(CorePhmm(layers))
} else {
Err(InvalidModelError::TooFewLayers(2).into())
}
}
#[inline]
#[must_use]
pub(crate) fn new_unchecked(layers: Vec<LayerParams<T, S>>) -> Self {
CorePhmm(layers)
}
}
impl<T, const S: usize> GetLayer<T, S> for CorePhmm<T, S> {
#[inline]
fn layers(&self) -> &[LayerParams<T, S>] {
self.0.as_slice()
}
#[inline]
fn split_last_layer(&self) -> (&LayerParams<T, S>, &[LayerParams<T, S>]) {
self.0.as_slice().split_last().expect("A CorePhmm has at least two layers")
}
}
impl<T, const S: usize> GetLayerMut<T, S> for CorePhmm<T, S> {
#[inline]
fn layers_mut(&mut self) -> &mut [LayerParams<T, S>] {
self.0.as_mut_slice()
}
#[inline]
fn layers_mut_vec(&mut self) -> &mut Vec<LayerParams<T, S>> {
&mut self.0
}
}