haddock_restraints/core/commands/
ti.rs1use crate::*;
2use std::error::Error;
3
4pub fn true_interface(
19 pdb: pdbtbx::PDB,
20 cutoff: &f64,
21 pml: &Option<String>,
22 pdb_path: &str,
23) -> Result<String, Box<dyn Error>> {
24 let true_interface = get_true_interface(&pdb, *cutoff);
25 let chains_in_contact = get_chains_in_contact(&pdb, *cutoff);
26
27 let mut true_interface: Vec<_> = true_interface.iter().collect();
29 true_interface.sort_by(|a, b| a.0.cmp(b.0));
30
31 let mut interactors: Vec<Interactor> = Vec::new();
34 for (chain_id, residues) in true_interface.iter() {
35 let target_id = pdb
37 .chains()
38 .position(|chain| chain.id() == *chain_id)
39 .unwrap();
40
41 let mut interactor = Interactor::new(target_id as u16);
42 interactor.set_chain(chain_id);
43 interactor.set_active(residues.iter().map(|&residue| residue as i16).collect());
44 interactor.set_pdb(pdb.clone());
45 interactor.remove_buried_residues();
46
47 for (chain_i, chain_j) in chains_in_contact.iter() {
49 let target_chain = if chain_i == *chain_id {
50 chain_j
51 } else {
52 chain_i
53 };
54 if let Some(target_index) = pdb.chains().position(|chain| chain.id() == *target_chain) {
55 interactor.add_target(target_index as u16);
56 }
57 }
58
59 interactors.push(interactor);
60 }
61
62 let air = Air::new(interactors);
64 let tbl = air.gen_tbl().unwrap();
65
66 println!("{}", tbl);
67
68 if let Some(output_f) = pml {
69 air.gen_pml(output_f, Some(pdb_path))
70 };
71
72 Ok(tbl)
73}
74
75pub fn unambig_ti(
90 pdb: pdbtbx::PDB,
91 cutoff: &f64,
92 pml: &Option<String>,
93 pdb_path: &str,
94) -> Result<String, Box<dyn Error>> {
95 let pairs = get_closest_residue_pairs(&pdb, *cutoff);
96
97 let mut interactors: Vec<Interactor> = Vec::new();
98 let mut counter = 0;
99 pairs.iter().for_each(|g| {
100 let mut interactor_i = Interactor::new(counter);
101 counter += 1;
102 let mut interactor_j = Interactor::new(counter);
103 interactor_j.add_target(counter - 1);
104 interactor_i.add_target(counter);
105 counter += 1;
106
107 interactor_i.set_chain(g.chain_i.as_str());
108 interactor_i.set_active(vec![g.res_i as i16]);
109 interactor_i.set_active_atoms(vec![g.atom_i.clone()]);
110 interactor_i.set_target_distance(g.distance);
111
112 interactor_j.set_chain(g.chain_j.as_str());
113 interactor_j.set_passive(vec![g.res_j as i16]);
114 interactor_j.set_passive_atoms(vec![g.atom_j.clone()]);
115
116 interactors.push(interactor_i);
117 interactors.push(interactor_j);
118 });
119
120 let air = Air::new(interactors);
122 let tbl = air.gen_tbl().unwrap();
123
124 println!("{}", tbl);
125
126 if let Some(output_f) = pml {
127 air.gen_pml(output_f, Some(pdb_path))
128 };
129
130 Ok(tbl)
131}
132
133pub fn list_interface(pdb: pdbtbx::PDB, cutoff: &f64) -> Result<(), Box<dyn Error>> {
150 let true_interface = get_true_interface(&pdb, *cutoff);
151
152 for (chain_id, residues) in true_interface.iter() {
153 let mut sorted_res = residues.iter().collect::<Vec<_>>();
154 sorted_res.sort();
155
156 println!("Chain {}: {:?}", chain_id, sorted_res);
157 }
158
159 Ok(())
160}
161#[cfg(test)]
162mod tests {
163
164 use super::*;
165 use std::io::{BufReader, Cursor};
166
167 #[test]
168 fn test_true_interface() {
169 let expected_tbl = r#"assign ( resid 933 and segid A )
170 (
171 ( resid 46 and segid B )
172 or
173 ( resid 47 and segid B )
174 ) 2.0 2.0 0.0
175
176assign ( resid 950 and segid A )
177 (
178 ( resid 46 and segid B )
179 or
180 ( resid 47 and segid B )
181 ) 2.0 2.0 0.0
182
183assign ( resid 46 and segid B )
184 (
185 ( resid 933 and segid A )
186 or
187 ( resid 950 and segid A )
188 ) 2.0 2.0 0.0
189
190assign ( resid 47 and segid B )
191 (
192 ( resid 933 and segid A )
193 or
194 ( resid 950 and segid A )
195 ) 2.0 2.0 0.0
196
197"#;
198
199 let content = std::fs::read_to_string("tests/data/complex.pdb").unwrap();
200 let mut opts = pdbtbx::ReadOptions::new();
201 opts.set_format(pdbtbx::Format::Pdb)
202 .set_level(pdbtbx::StrictnessLevel::Loose);
203 let cursor = Cursor::new(content.into_bytes());
204 let reader = BufReader::new(cursor);
205 let (pdb, _) = opts.read_raw(reader).unwrap();
206
207 let opt: Option<String> = None;
208 match true_interface(pdb, &3.0, &opt, "tests/data/complex.pdb") {
209 Ok(tbl) => assert_eq!(tbl, expected_tbl),
210 Err(_e) => (),
211 };
212 }
213 #[test]
214 fn test_true_interface_ba() {
215 let expected_tbl = r#"assign ( resid 933 and segid A )
216 (
217 ( resid 46 and segid B )
218 or
219 ( resid 47 and segid B )
220 ) 2.0 2.0 0.0
221
222assign ( resid 950 and segid A )
223 (
224 ( resid 46 and segid B )
225 or
226 ( resid 47 and segid B )
227 ) 2.0 2.0 0.0
228
229assign ( resid 46 and segid B )
230 (
231 ( resid 933 and segid A )
232 or
233 ( resid 950 and segid A )
234 ) 2.0 2.0 0.0
235
236assign ( resid 47 and segid B )
237 (
238 ( resid 933 and segid A )
239 or
240 ( resid 950 and segid A )
241 ) 2.0 2.0 0.0
242
243"#;
244
245 let content = std::fs::read_to_string("tests/data/complex_BA.pdb").unwrap();
246 let mut opts = pdbtbx::ReadOptions::new();
247 opts.set_format(pdbtbx::Format::Pdb)
248 .set_level(pdbtbx::StrictnessLevel::Loose);
249 let cursor = Cursor::new(content.into_bytes());
250 let reader = BufReader::new(cursor);
251 let (pdb, _) = opts.read_raw(reader).unwrap();
252
253 let opt: Option<String> = None;
254 match true_interface(pdb, &3.0, &opt, "tests/data/complex_BA.pdb") {
255 Ok(tbl) => assert_eq!(tbl, expected_tbl),
256 Err(_e) => (),
257 };
258 }
259
260 #[test]
261 fn test_unambigti() {
262 let content = std::fs::read_to_string("tests/data/two_res.pdb").unwrap();
263 let mut opts = pdbtbx::ReadOptions::new();
264 opts.set_format(pdbtbx::Format::Pdb)
265 .set_level(pdbtbx::StrictnessLevel::Loose);
266 let cursor = Cursor::new(content.into_bytes());
267 let reader = BufReader::new(cursor);
268 let (pdb, _) = opts.read_raw(reader).unwrap();
269
270 let opt: Option<String> = None;
271 let expected_tbl = "assign ( resid 2 and segid A and name CA ) ( resid 10 and segid B and name CA ) 9.1 2.0 0.0\n\n";
272
273 match unambig_ti(pdb, &5.0, &opt, "tests/data/two_res.pdb") {
274 Ok(tbl) => assert_eq!(tbl, expected_tbl),
275 Err(_e) => (),
276 }
277 }
278}