use crate::shared::Dna;
use crate::shared::{DAlignment, VJAlignment};
use crate::vdj::Model;
use anyhow::{anyhow, Result};
#[cfg(all(feature = "py_binds", feature = "pyo3"))]
use pyo3::prelude::*;
#[derive(Default)]
pub struct Event<'a> {
pub v: Option<&'a VJAlignment>,
pub j: Option<&'a VJAlignment>,
pub d: Option<&'a DAlignment>,
pub delv: usize,
pub delj: usize,
pub deld3: usize,
pub deld5: usize,
}
#[cfg_attr(all(feature = "py_binds", feature = "pyo3"), pyclass(get_all, set_all))]
#[derive(Default, Clone, Debug, PartialEq, Eq)]
pub struct StaticEvent {
pub v_index: usize,
pub v_start_gene: usize, pub delv: usize,
pub j_index: usize,
pub j_start_seq: usize, pub delj: usize,
pub d_index: usize,
pub d_start_seq: usize,
pub deld3: usize,
pub deld5: usize,
pub insvd: Dna,
pub insdj: Dna,
pub errors: Vec<(usize, u8)>,
}
#[cfg(all(feature = "py_binds", feature = "pyo3"))]
#[pymethods]
impl StaticEvent {
fn __repr__(&self) -> String {
format!(
"StaticEvent(\n\
nb. del. on V3: {},\n\
nb. del. on D5: {},\n\
nb. del. on D3: {},\n\
nb. del. on J5: {},\n\
V-D insertions: {},\n\
D-J insertions: {})",
self.delv,
self.deld5,
self.deld3,
self.delj,
self.insvd.get_string(),
self.insdj.get_string()
)
}
}
impl StaticEvent {
pub fn to_sequence(&self, m: &Model) -> Dna {
let seq_v: &Dna = m.seg_vs[self.v_index].seq_with_pal.as_ref().unwrap();
let seq_j: &Dna = m.seg_js[self.j_index].seq_with_pal.as_ref().unwrap();
let seq_d: &Dna = m.seg_ds[self.d_index].seq_with_pal.as_ref().unwrap();
let mut seq: Dna = Dna::new();
seq.extend(&seq_v.extract_subsequence(0, seq_v.len() - self.delv));
seq.extend(&self.insvd);
seq.extend(&seq_d.extract_subsequence(self.deld5, seq_d.len() - self.deld3));
seq.extend(&self.insdj);
seq.extend(&seq_j.extract_subsequence(self.delj, seq_j.len()));
for (ii, nuc) in &self.errors {
seq.seq[*ii] = *nuc
}
seq
}
pub fn extract_cdr3(&self, full_sequence: &Dna, m: &Model) -> Dna {
let vg = &m.seg_vs[self.v_index];
let jg = &m.seg_js[self.j_index];
let mut end_cdr3 = full_sequence.len() - jg.seq.len() + jg.cdr3_pos.unwrap() + 3;
if vg.cdr3_pos.unwrap() > end_cdr3 {
end_cdr3 = vg.cdr3_pos.unwrap(); }
full_sequence.extract_subsequence(vg.cdr3_pos.unwrap(), end_cdr3)
}
pub fn to_cdr3(&self, m: &Model) -> Dna {
let full_sequence = self.to_sequence(m);
self.extract_cdr3(&full_sequence, m)
}
}
impl Event<'_> {
pub fn to_static(&self, insvd: Dna, insdj: Dna) -> Result<StaticEvent> {
Ok(StaticEvent {
v_index: self
.v
.ok_or(anyhow!("Can't move that event to static"))?
.index,
v_start_gene: self
.v
.ok_or(anyhow!("Can't move that event to static"))?
.start_gene,
delv: self.delv,
j_index: self
.j
.ok_or(anyhow!("Can't move that event to static"))?
.index,
j_start_seq: self
.j
.ok_or(anyhow!("Can't move that event to static"))?
.start_seq,
delj: self.delj,
d_index: self
.d
.ok_or(anyhow!("Can't move that event to static"))?
.index,
d_start_seq: self
.d
.ok_or(anyhow!("Can't move that event to static"))?
.pos,
deld3: self.deld3,
deld5: self.deld5,
insvd,
insdj,
..Default::default()
})
}
}