use crate::progressive::{dist2offset, make_dynamic_matrix};
pub const NDISTCLASS: usize = 10;
pub fn calc_max_dist_class(unalign_level: f64) -> usize {
let mut c = 0usize;
while c < NDISTCLASS {
let rep = 2.0 * c as f64 / NDISTCLASS as f64; if dist2offset(rep, unalign_level) == 0.0 {
break;
}
c += 1;
}
c + 1
}
pub fn make_scoring_matrices(
base: &[Vec<f64>],
unalign_level: f64,
gap_idx: usize,
max_dist_class: usize,
) -> Vec<Vec<Vec<f64>>> {
(0..max_dist_class)
.map(|c| {
let rep = 2.0 * c as f64 / NDISTCLASS as f64; make_dynamic_matrix(base, rep * 0.5, unalign_level, gap_idx)
})
.collect()
}
pub struct PairClassification {
pub matnum: Vec<Vec<usize>>,
pub eff1s: Vec<Vec<f64>>,
pub eff2s: Vec<Vec<f64>>,
}
pub fn classify_pairs(
eff1: &[f64],
eff2: &[f64],
smalldist: &[Vec<f64>],
max_dist_class: usize,
) -> PairClassification {
let n1 = eff1.len();
let n2 = eff2.len();
let mut eff1s = vec![vec![0.0f64; n1]; max_dist_class];
let mut eff2s = vec![vec![0.0f64; n2]; max_dist_class];
let mut matnum = vec![vec![0usize; n2]; n1];
for i in 0..n1 {
for j in 0..n2 {
let mut c = (smalldist[i][j] / 2.0 * NDISTCLASS as f64) as usize;
if c >= max_dist_class {
c = max_dist_class - 1;
}
eff1s[c][i] = eff1[i];
eff2s[c][j] = eff2[j];
matnum[i][j] = c;
}
}
PairClassification { matnum, eff1s, eff2s }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn max_dist_class_for_allowshift_is_9() {
assert_eq!(calc_max_dist_class(0.8), 9);
}
#[test]
fn max_dist_class_disabled_is_1() {
assert_eq!(calc_max_dist_class(0.0), 1);
}
#[test]
fn scoring_matrices_count_and_c0_is_base() {
let base = vec![vec![10.0, -2.0, 0.0], vec![-2.0, 8.0, 1.0], vec![0.0, 1.0, 5.0]];
let mats = make_scoring_matrices(&base, 0.8, 2, calc_max_dist_class(0.8));
assert_eq!(mats.len(), 9);
assert_eq!(mats[8][0][0], base[0][0]);
assert_eq!(mats[8][0][1], base[0][1]);
}
#[test]
fn classify_pairs_bins_and_clamps() {
let eff1 = vec![0.5, 0.5];
let eff2 = vec![1.0];
let smalldist = vec![vec![0.4], vec![3.0]];
let pc = classify_pairs(&eff1, &eff2, &smalldist, 9);
assert_eq!(pc.matnum[0][0], 2);
assert_eq!(pc.matnum[1][0], 8);
assert_eq!(pc.eff1s[2][0], 0.5);
assert_eq!(pc.eff1s[8][1], 0.5);
assert_eq!(pc.eff2s[2][0], 1.0);
assert_eq!(pc.eff2s[8][0], 1.0);
}
}