use crate::backtranslate::codon::{Codon, CodonTable};
pub fn translate_cds_to_protein(cds_sequence: &str) -> Option<String> {
let table = CodonTable::standard();
let mut protein = String::new();
let codon_count = cds_sequence.len() / 3;
for i in 0..codon_count {
let start = i * 3;
let codon_str = &cds_sequence[start..start + 3];
if let Some(codon) = Codon::parse(codon_str) {
if table.is_stop(&codon) {
break; }
if let Some(aa) = table.amino_acid_for(&codon) {
use crate::hgvs::location::AminoAcid;
let _: &AminoAcid = aa; protein.push(aa.to_one_letter());
} else {
return None; }
} else {
return None; }
}
Some(protein)
}
pub fn derive_protein_from_transcript(
transcript_seq: &str,
cds_start: usize,
cds_end: usize,
) -> Option<String> {
if cds_end > transcript_seq.len() || cds_start >= cds_end {
return None;
}
let cds = &transcript_seq[cds_start..cds_end];
translate_cds_to_protein(cds)
}
pub fn cds_coords_to_indices(cds_start: u64, cds_end: u64) -> (usize, usize) {
((cds_start - 1) as usize, cds_end as usize)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_translate_simple() {
assert_eq!(
translate_cds_to_protein("ATGTGGTAA"),
Some("MW".to_string())
);
}
#[test]
fn test_translate_no_stop() {
assert_eq!(translate_cds_to_protein("ATGTGG"), Some("MW".to_string()));
}
#[test]
fn test_translate_invalid() {
assert_eq!(translate_cds_to_protein("ATGNTG"), None);
}
#[test]
fn test_derive_protein() {
let transcript = "AAAATGTGGTAAGGG";
assert_eq!(
derive_protein_from_transcript(transcript, 3, 12),
Some("MW".to_string())
);
}
#[test]
fn test_derive_protein_invalid_coords() {
let transcript = "ATGTGGTAA";
assert_eq!(derive_protein_from_transcript(transcript, 5, 3), None);
assert_eq!(derive_protein_from_transcript(transcript, 0, 100), None);
}
#[test]
fn test_cds_coords_conversion() {
assert_eq!(cds_coords_to_indices(1, 10), (0, 10));
assert_eq!(cds_coords_to_indices(100, 500), (99, 500));
}
}