pub trait Alphabet: Copy + Clone + Sized + Send + Sync {
const N_STATES: usize;
const CANONICAL: &'static [u8];
const GAP: u8;
fn profile(c: u8) -> Option<Vec<f64>>;
fn index_of(c: u8) -> Option<usize>;
fn char_of(i: usize) -> u8;
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Nucleotide;
impl Alphabet for Nucleotide {
const N_STATES: usize = 4;
const CANONICAL: &'static [u8] = b"ACGT";
const GAP: u8 = b'-';
fn index_of(c: u8) -> Option<usize> {
match c {
b'A' => Some(0),
b'C' => Some(1),
b'G' => Some(2),
b'T' | b'U' => Some(3),
_ => None,
}
}
fn char_of(i: usize) -> u8 {
Self::CANONICAL[i]
}
fn profile(c: u8) -> Option<Vec<f64>> {
match c {
b'A' => Some(vec![1.0, 0.0, 0.0, 0.0]),
b'C' => Some(vec![0.0, 1.0, 0.0, 0.0]),
b'G' => Some(vec![0.0, 0.0, 1.0, 0.0]),
b'T' | b'U' => Some(vec![0.0, 0.0, 0.0, 1.0]),
b'R' => Some(vec![0.5, 0.0, 0.5, 0.0]), b'Y' => Some(vec![0.0, 0.5, 0.0, 0.5]), b'S' => Some(vec![0.0, 0.5, 0.5, 0.0]), b'W' => Some(vec![0.5, 0.0, 0.0, 0.5]), b'K' => Some(vec![0.0, 0.0, 0.5, 0.5]), b'M' => Some(vec![0.5, 0.5, 0.0, 0.0]), b'B' => Some(vec![0.0, 1.0/3.0, 1.0/3.0, 1.0/3.0]), b'D' => Some(vec![1.0/3.0, 0.0, 1.0/3.0, 1.0/3.0]), b'H' => Some(vec![1.0/3.0, 1.0/3.0, 0.0, 1.0/3.0]), b'V' => Some(vec![1.0/3.0, 1.0/3.0, 1.0/3.0, 0.0]), b'N' => Some(vec![0.25, 0.25, 0.25, 0.25]),
Self::GAP => Some(vec![1.0; 4]),
_ => None,
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct AminoAcid;
impl Alphabet for AminoAcid {
const N_STATES: usize = 20;
const CANONICAL: &'static [u8] = b"ACDEFGHIKLMNPQRSTVWY";
const GAP: u8 = b'-';
fn index_of(c: u8) -> Option<usize> {
Self::CANONICAL.iter().position(|&x| x == c)
}
fn char_of(i: usize) -> u8 {
Self::CANONICAL[i]
}
fn profile(c: u8) -> Option<Vec<f64>> {
if let Some(idx) = Self::index_of(c) {
let mut p = vec![0.0; 20];
p[idx] = 1.0;
return Some(p);
}
match c {
b'B' => { let mut p = vec![0.0; 20];
p[3] = 0.5; p[11] = 0.5; Some(p)
}
b'Z' => { let mut p = vec![0.0; 20];
p[4] = 0.5; p[14] = 0.5; Some(p)
}
b'J' => { let mut p = vec![0.0; 20];
p[8] = 0.5; p[9] = 0.5; Some(p)
}
b'X' | Self::GAP => Some(vec![1.0; 20]),
_ => None,
}
}
}