protein_analysis/
model.rs1use dihedral::dihedral;
2use protein_core::structure::{Model, Residue};
3
4pub trait ModelAnalysis {
5 fn ramachandran(&self) -> (Vec<f32>, Vec<f32>);
6}
7
8impl ModelAnalysis for Model {
9 fn ramachandran(&self) -> (Vec<f32>, Vec<f32>) {
10 let mut n: Vec<[f32; 3]> = Default::default();
11 let mut ca: Vec<[f32; 3]> = Default::default();
12 let mut c: Vec<[f32; 3]> = Default::default();
13
14 let mut i = 0;
15 while i < self.atoms.len() {
16 if let Residue::AminoAcid(_) = self.atoms[i].residue {
17 if self.atoms[i].name.0 == b"N "[..]&& self.atoms[i + 1].name.0 == b"CA "[..] && self.atoms[i + 2].name.0 == b"C "[..]
20 {
22 n.push(self.atoms[i].coord);
23 ca.push(self.atoms[i + 1].coord);
24 c.push(self.atoms[i + 2].coord);
25 i += 3;
26 continue;
27 }
28 }
29 i += 1;
30 }
31 assert!(n.len() == ca.len() && n.len() == c.len());
32 let mut phis = Vec::new();
33 let mut psis = Vec::new();
34 for i in 1..n.len() - 1 {
35 let phi = dihedral(&[c[i - 1], n[i], ca[i], c[i]]);
36 let psi = dihedral(&[n[i], ca[i], c[i], n[i + 1]]);
37 phis.push(phi.to_degrees());
38 psis.push(psi.to_degrees());
39 }
40 (phis, psis)
41 }
42}