use crate::codon::CodonTable;
use crate::core::{MomaRing, OriginStrategy};
use crate::mutation::Mutation;
use std::marker::PhantomData;
pub struct BioSigAnalyzer<S: OriginStrategy> {
ring: MomaRing<S>,
codon_table: CodonTable,
_strategy: PhantomData<S>,
}
impl<S: OriginStrategy> BioSigAnalyzer<S> {
pub fn new(modulus: u64, strategy: S) -> Self {
Self {
ring: MomaRing::new(modulus, strategy),
codon_table: CodonTable::new(),
_strategy: PhantomData,
}
}
pub fn analyze(&self, p: u64, dna_sequence: &str) -> Option<(u64, Mutation)> {
let signature = self.ring.signature(p);
let mutation_pos = (signature % dna_sequence.len() as u64) as usize;
let codon_start = (mutation_pos / 3) * 3;
if codon_start + 3 > dna_sequence.len() {
return None; }
let original_codon_str = &dna_sequence[codon_start..codon_start + 3];
let original_aa = self.codon_table.translate(original_codon_str)?;
let mut mutated_sequence = dna_sequence.to_string();
let original_char = mutated_sequence.chars().nth(mutation_pos).unwrap();
let new_char = match original_char {
'A' => 'C',
'C' => 'G',
'G' => 'T',
'T' => 'A',
_ => return None, };
mutated_sequence.replace_range(mutation_pos..mutation_pos + 1, &new_char.to_string());
let mutated_codon_str = &mutated_sequence[codon_start..codon_start + 3];
let mutated_aa = self.codon_table.translate(mutated_codon_str)?;
let mutation = Mutation::new(
original_codon_str.to_string(),
mutated_codon_str.to_string(),
original_aa,
mutated_aa,
);
Some((signature, mutation))
}
}