1use std::collections::HashMap;
2use std::env;
3use std::fs;
4use std::fs::File;
5use std::io::prelude::BufRead;
6use std::io::BufReader;
7use std::process;
8
9use crate::structures::atom::Atom;
10use crate::structures::structure::Structure;
11use crate::structures::*;
12
13pub fn fasta_seq(my_struct: &Structure) -> String {
25 let res: HashMap<&str, char> = [
26 ("ARG", 'R'),
27 ("LYS", 'K'),
28 ("ASN", 'N'),
29 ("ASP", 'D'),
30 ("GLU", 'E'),
31 ("SER", 'S'),
32 ("THR", 'T'),
33 ("GLN", 'Q'),
34 ("CYS", 'C'),
35 ("HIS", 'H'),
36 ("HSD", 'H'),
37 ("HSP", 'H'),
38 ("HSD", 'H'),
39 ("SEC", 'U'),
40 ("GLY", 'G'),
41 ("PRO", 'P'),
42 ("ALA", 'A'),
43 ("VAL", 'V'),
44 ("ILE", 'I'),
45 ("LEU", 'L'),
46 ("MET", 'M'),
47 ("PHE", 'P'),
48 ("TYR", 'Y'),
49 ("TRP", 'W'),
50 ]
51 .iter()
52 .cloned()
53 .collect();
54
55 let mut fasta = String::with_capacity(my_struct.get_residue_number() as usize);
57
58 for chain in &my_struct.chains {
59 for residue in &chain.lst_res {
60 if let Some(r) = res.get(&residue.name()[..]) {
61 fasta.push(*r);
62 }
63 }
64 }
65 fasta
66}
67
68pub fn rmsd<T: GetAtom>(first: &T, second: &T) -> Result<f32, &'static str> {
87 let atoms_first = first.get_atom();
88 let atoms_second = second.get_atom();
89
90 if atoms_first.len() != atoms_second.len() {
92 return Err("Different number of atoms");
93 }
94 let mut total = 0.0;
95 for index in 0..atoms_first.len() {
96 let coord_first = &atoms_first[index].coord;
97 let coord_second = &atoms_second[index].coord;
98 total += (coord_first[0] - coord_second[0]).powi(2)
99 + (coord_first[1] - coord_second[1]).powi(2)
100 + (coord_first[2] - coord_second[2]).powi(2)
101 }
102 Ok((total / atoms_first.len() as f32).sqrt())
103}
104
105pub fn atom_mass() -> HashMap<String, f32> {
109 let mut ref_masses: HashMap<String, f32> = HashMap::new();
110
111 let key = "CHARMM_FOLDER";
113 let charmm_folder = match env::var(key) {
114 Ok(charmm_folder) => charmm_folder,
115 _ => "./datasets".to_string(),
116 };
117 let paths = match fs::read_dir(charmm_folder) {
118 Ok(paths) => paths,
119 Err(_e) => {
120 eprintln!("cannot find your charmm folder");
121 process::exit(1);
122 }
123 };
124
125 for path in paths {
126 let test = path.unwrap().path();
127 if test.is_file() && test.extension().unwrap().to_str() == Some("prm") {
128 let charmmf = match File::open(test) {
129 Ok(charmmf) => charmmf,
130 Err(e) => {
131 eprintln!("Error while reading {}", e);
132 process::exit(1);
133 }
134 };
135
136 let reader = BufReader::new(charmmf);
137 for line in reader.lines() {
138 let l = line.unwrap();
140 if l.starts_with("MASS") {
141 let split: Vec<&str> = l.split_ascii_whitespace().collect();
142 let val = match split[3].parse::<f32>() {
143 Ok(val) => val,
144 Err(e) => {
145 eprintln!("Cannot cast {} into f32", e);
146 process::exit(1);
147 }
148 };
149 ref_masses.insert(split[2].to_string(), val);
150 }
151 }
152 }
153 }
154 return ref_masses;
155}
156
157impl GetAtom for std::vec::Vec<Atom> {
159 fn get_atom(&self) -> Vec<&Atom> {
160 let mut lst_atom: Vec<&Atom> = Vec::with_capacity(self.len());
161 for atom in self.iter() {
162 lst_atom.push(&atom)
163 }
164 lst_atom
165 }
166
167 fn compute_weight(&self) -> f32 {
168 self.get_atom().iter().map(|x| x.get_weight()).sum()
169 }
170}