use crate::data::byte_types::ByteMappings;
#[must_use]
pub fn dna_substitution_matrix(seq1: &[u8], seq2: &[u8]) -> [[u32; 4]; 4] {
let mut sub_matrix = [[0u32; 4]; 4];
std::iter::zip(
seq1.iter().copied().map(ByteMappings::to_dna_index),
seq2.iter().copied().map(ByteMappings::to_dna_index),
)
.filter(|(a, b)| *a < 4 && *b < 4)
.for_each(|(a, b)| sub_matrix[a][b] += 1);
sub_matrix
}
#[allow(clippy::needless_range_loop)]
#[inline]
#[must_use]
pub(crate) fn hamming_dist_from_sub_matrix(sub_matrix: &[[u32; 4]; 4]) -> u32 {
let mut hamming = 0;
for i in 0..4 {
for j in 0..4 {
if i != j {
hamming += sub_matrix[i][j];
}
}
}
hamming
}
#[must_use]
pub(crate) fn total_and_frequencies(sub_matrix: &[[u32; 4]; 4]) -> (u32, [f64; 4]) {
let mut bf = [0f64; 4];
for i in 0..4 {
bf[i] = f64::from(sub_matrix[i].iter().sum::<u32>() + sub_matrix.iter().map(|row| row[i]).sum::<u32>());
}
let total_bases = sub_matrix.iter().flatten().sum::<u32>();
for freq in &mut bf {
*freq /= 2.0 * f64::from(total_bases);
}
(total_bases, bf)
}