use crate::locate::LocateIndex;
pub(super) fn predicts_nmd(cds_position: u32, index: &LocateIndex) -> bool {
let cds_end_exon = match index.cds_end_exon_idx() {
Some(idx) => idx,
None => return false, };
let last_seg_idx = match index.exon_to_cds_seg().get(cds_end_exon) {
Some(Some(seg)) => *seg as usize,
_ => return false,
};
if last_seg_idx == 0 {
return false;
}
let last_junction_cds_pos = index.cumulative_cds()[last_seg_idx] + 1;
if cds_position >= last_junction_cds_pos {
return false;
}
last_junction_cds_pos - cds_position > 50
}
#[cfg(test)]
mod tests {
use super::*;
use crate::locate::LocateIndex;
use crate::test_fixtures::{minus_strand_coding, plus_strand_coding};
fn build_index(tx: &crate::types::TranscriptModel) -> LocateIndex {
LocateIndex::build(tx).unwrap()
}
#[test]
fn nmd_ptc_far_upstream() {
let tx = plus_strand_coding();
let idx = build_index(&tx);
assert!(predicts_nmd(100, &idx));
}
#[test]
fn nmd_ptc_in_last_exon() {
let tx = plus_strand_coding();
let idx = build_index(&tx);
assert!(!predicts_nmd(1100, &idx));
}
#[test]
fn nmd_ptc_within_50nt() {
let tx = plus_strand_coding();
let idx = build_index(&tx);
assert!(!predicts_nmd(960, &idx));
}
#[test]
fn nmd_ptc_exactly_at_50nt() {
let tx = plus_strand_coding();
let idx = build_index(&tx);
assert!(!predicts_nmd(951, &idx));
}
#[test]
fn nmd_ptc_at_51nt() {
let tx = plus_strand_coding();
let idx = build_index(&tx);
assert!(predicts_nmd(950, &idx));
}
#[test]
fn nmd_single_exon() {
use crate::types::*;
let tx = TranscriptModel {
accession: "NM_SINGLE.1".into(),
protein_accession: Some("NP_SINGLE.1".into()),
gene_symbol: "SINGLE".into(),
hgnc_id: None,
ensembl_accession: None,
chrom: "chr1".into(),
strand: Strand::Plus,
tx_start: 0,
tx_end: 300,
cds_genomic_start: Some(100),
cds_genomic_end: Some(200),
exons: vec![Exon {
exon_number: 1,
genomic_start: 0,
genomic_end: 300,
}],
cds_segments: vec![CdsSegment {
exon_index: 0,
genomic_start: 100,
genomic_end: 200,
phase: 0,
}],
tier: TranscriptTier::ManeSelect,
biotype: Biotype::ProteinCoding,
exon_count: 1,
};
let idx = build_index(&tx);
assert!(!predicts_nmd(10, &idx));
}
#[test]
fn nmd_minus_strand() {
let tx = minus_strand_coding();
let idx = build_index(&tx);
assert!(predicts_nmd(100, &idx));
assert!(!predicts_nmd(3500, &idx));
}
}