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