use crate::Design;
use std::io::Write;
use itertools::Itertools;
use std::collections::HashMap;
fn save_as_np_txt<W: Write>(
mut w: W,
position_list: &Vec<[f64; 3]>,
stack_list: &Vec<isize>,
three_prime_list: &Vec<isize>,
basepair_list: &Vec<isize>,
) -> Result<(), anyhow::Error> {
for i in 0..position_list.len() {
write!(
w,
"{:.} {:.} {:.} {} {} {}\n",
position_list[i][0],
position_list[i][1],
position_list[i][2],
basepair_list[i],
stack_list[i],
three_prime_list[i],
)?;
}
Ok(())
}
impl<StrandLabel, DomainLabel> Design<StrandLabel, DomainLabel> {
pub fn to_mrdna<W: Write>(&self, w: W) -> Result<(), anyhow::Error> {
let nucl_map = self.get_nucl_map();
let mut nucl_number = HashMap::new();
let mut stack: HashMap<(isize, isize, bool), (isize, isize, bool)> = HashMap::new();
let mut three_prime: HashMap<(isize, isize, bool), (isize, isize, bool)> = HashMap::new();
let mut basepair: HashMap<(isize, isize, bool), (isize, isize, bool)> = HashMap::new();
let mut position_list = vec![[0., 0., 0.]; nucl_map.len()];
for (r_nucl, _strands) in nucl_map.iter() {
let nucl = *r_nucl;
let (helix, n, forward) = nucl;
let next_nucl = (helix, if forward { n + 1 } else { n - 1 }, forward);
if nucl_map.contains_key(&next_nucl) {
stack.insert(nucl, next_nucl);
}
}
let mut i_nucl_max = 0;
for i in 0..self.strands.len() {
let s = &self.strands[i];
let mut v_strand = Vec::new();
for d in &s.domains {
for n in d.iter() {
let nucl = (d.helix, n, d.forward);
nucl_number.insert(nucl, i_nucl_max); position_list[i_nucl_max] = self.space_pos(d.helix, n, d.forward); if nucl_map.contains_key(&(d.helix, n, !d.forward)) {
basepair.insert(nucl, (d.helix, n, !d.forward));
}
i_nucl_max += 1;
v_strand.push(nucl);
}
}
for (r_nucl_prev, r_nucl_next) in v_strand.iter().tuple_windows() {
let nucl_prev = *r_nucl_prev;
let nucl_next = *r_nucl_next;
three_prime.insert(nucl_prev, nucl_next);
let nucleotides_linked = |n1, n2| {
let v_d1 = &nucl_map.get(n1);
let v_d2 = &nucl_map.get(n2);
if v_d1.is_some() && v_d2.is_some() {
match (v_d1.unwrap().last(), v_d2.unwrap().last()) {
(Some(d1), Some(d2)) => d1 == d2, _ => false,
}
} else {
false
}
};
let _stack_exists = {
let (helix1, n1, forward1) = nucl_prev;
let (helix2, n2, forward2) = nucl_next;
if helix1 == helix2 {
true
} else {
let nucl_stack1 = if forward1 {
(helix1, n1 + 1, forward1)
} else {
(helix1, n1 - 1, forward1)
};
let nucl_stack2 = if forward2 {
(helix2, n2 - 1, forward2)
} else {
(helix2, n2 + 1, forward2)
};
nucleotides_linked(&nucl_stack1, &nucl_stack2)
}
};
}
}
let to_list = |hashmap: HashMap<(isize, isize, bool), (isize, isize, bool)>| {
let mut v = vec![-1; nucl_map.len()];
for (k_n, n) in hashmap.iter() {
v[nucl_number[k_n]] = nucl_number[n] as isize;
}
v
};
assert!(
basepair.len() > 0,
"mrdna does not accept design only with single strands"
);
let stack_list = to_list(stack);
let three_prime_list = to_list(three_prime);
let basepair_list = to_list(basepair);
assert!(
{
let len_p = position_list.len();
stack_list.len() == len_p
&& three_prime_list.len() == len_p
&& basepair_list.len() == len_p
},
"all the len must be equal"
);
save_as_np_txt::<W>(
w,
&position_list,
&stack_list,
&three_prime_list,
&basepair_list,
)
}
}