10 def _Setup(mdl, ref, mdl_ch1, mdl_ch2, ref_ch1, ref_ch2):
11 """ Performs parameter checks and dumps files for DockQ
13 In case of dimeric interfaces the respective chains are selected from
14 mdl/trg, renamed to A/B and dumped to disk.
16 In case of interfaces with more chains involved, we simply select the
17 specified chains and do no renaming before dumping to disk.
19 if isinstance(mdl_ch1, str):
21 if isinstance(mdl_ch2, str):
23 if isinstance(ref_ch1, str):
25 if isinstance(ref_ch2, str):
29 raise RuntimeError(
"mdl_ch1 is empty")
31 raise RuntimeError(
"mdl_ch2 is empty")
33 if len(mdl_ch1) != len(ref_ch1):
34 raise RuntimeError(
"mdl_ch1/ref_ch1 inconsistent in size")
35 if len(mdl_ch2) != len(ref_ch2):
36 raise RuntimeError(
"mdl_ch2/ref_ch2 inconsistent in size")
39 ch = mdl.FindChain(cname)
41 raise RuntimeError(f
"Chain {cname} specified in mdl_ch1 not "
45 ch = mdl.FindChain(cname)
47 raise RuntimeError(f
"Chain {cname} specified in mdl_ch2 not "
51 ch = ref.FindChain(cname)
53 raise RuntimeError(f
"Chain {cname} specified in ref_ch1 not "
57 ch = ref.FindChain(cname)
59 raise RuntimeError(f
"Chain {cname} specified in ref_ch2 not "
62 mdl_to_dump = mdl.CreateFullView()
63 ref_to_dump = ref.CreateFullView()
65 if len(mdl_ch1) == 1
and len(mdl_ch2) == 1:
68 mdl_to_dump = mol.CreateEntityFromView(mdl_to_dump,
True)
69 tmp = mol.CreateEntity()
71 ch1 = mdl_to_dump.FindChain(mdl_ch1[0])
72 ed.InsertChain(
"A", ch1, deep=
True)
73 ch2 = mdl_to_dump.FindChain(mdl_ch2[0])
74 ed.InsertChain(
"B", ch2, deep=
True)
80 ref_to_dump = mol.CreateEntityFromView(ref_to_dump,
True)
81 tmp = mol.CreateEntity()
83 ch1 = ref_to_dump.FindChain(ref_ch1[0])
84 ed.InsertChain(
"A", ch1, deep=
True)
85 ch2 = ref_to_dump.FindChain(ref_ch2[0])
86 ed.InsertChain(
"B", ch2, deep=
True)
92 raise NotImplementedError(
"DockQ computations beyond two interacting "
93 "chains has not been properly tested...")
101 mdl_str = io.EntityToPDBStr(mdl_to_dump)
102 ref_str = io.EntityToPDBStr(ref_to_dump)
104 tmp_dir = tempfile.mkdtemp()
105 with open(os.path.join(tmp_dir,
"mdl.pdb"),
'w')
as fh:
107 with open(os.path.join(tmp_dir,
"ref.pdb"),
'w')
as fh:
110 return (tmp_dir, mdl_ch1, mdl_ch2, ref_ch1, ref_ch2)
113 """ DockQ result object
115 def __init__(self, Fnat, Fnonnat, native_contacts, model_contacts, iRMS,
127 """ DockQ - Fnat output
129 :type: :class:`float`
135 """ DockQ - Fnonnat output
137 :type: :class:`float`
143 """ DockQ - number native contacts
151 """ DockQ - number model contacts
159 """ DockQ - iRMS output
161 :type: :class:`float`
167 """ DockQ - LMRS output
169 :type: :class:`float`
175 """ DockQ - DockQ output
177 :type: :class:`float`
182 """ Returns JSON serializable summary
184 return {
"Fnat": self.
Fnat,
194 """ Static constructor from raw DockQ output
196 :param output: Raw output from DockQ executable
197 :type output: :class:`str`
198 :returns: Object of type :class:`DockQResult`
202 native_contacts =
None
203 model_contacts =
None
208 for line
in output.splitlines():
209 if line.startswith(
'*'):
211 if line.startswith(
"Fnat"):
212 Fnat = float(line.split()[1])
213 native_contacts = int(line.split()[5])
214 elif line.startswith(
"Fnonnat"):
215 Fnonnat = float(line.split()[1])
216 model_contacts = int(line.split()[5])
217 elif line.startswith(
"iRMS"):
218 iRMS = float(line.split()[1])
219 elif line.startswith(
"LRMS"):
220 LRMS = float(line.split()[1])
221 elif line.startswith(
"DockQ"):
222 DockQ = float(line.split()[1])
224 return DockQResult(Fnat, Fnonnat, native_contacts, model_contacts,
228 def DockQ(dockq_exec, mdl, ref, mdl_ch1, mdl_ch2, ref_ch1,
230 """ Computes DockQ for specified interface
232 DockQ is available from https://github.com/bjornwallner/DockQ -
233 For this binding to work, DockQ must be properly installed and its
234 dependencies must be available (numpy, Biopython).
236 :param dockq_exec: Path to DockQ.py script from DockQ repository
237 :type dockq_exec: :class:`str`
238 :param mdl: Model structure
239 :type mdl: :class:`ost.mol.EntityView`/:class:`ost.mol.EntityHandle`
240 :param ref: Reference structure, i.e. native structure
241 :type ref: :class:`ost.mol.EntityView`/:class:`ost.mol.EntityHandle`
242 :param mdl_ch1: Specifies chain(s) in model constituting first part of
244 :type mdl_ch1: :class:`str`/:class:`list` of :class:`str`
245 :param mdl_ch2: Specifies chain(s) in model constituting second part of
247 :type mdl_ch2: :class:`str`/:class:`list` of :class:`str`
248 :param ref_ch1: ref equivalent of mdl_ch1
249 :type ref_ch1: :class:`str`/:class:`list` of :class:`str`
250 :param ref_ch2: ref equivalent of mdl_ch2
251 :type ref_ch2: :class:`str`/:class:`list` of :class:`str`
252 :returns: Result object of type :class:`DockQResult`
254 if not os.path.exists(dockq_exec):
255 raise RuntimeError(f
"DockQ executable ({dockq_exec}) does not exist")
257 tmp_dir, mdl_ch1, mdl_ch2, ref_ch1, ref_ch2 = \
258 _Setup(mdl, ref, mdl_ch1, mdl_ch2, ref_ch1, ref_ch2)
260 cmd = [sys.executable, dockq_exec, os.path.join(tmp_dir,
"mdl.pdb"),
261 os.path.join(tmp_dir,
"ref.pdb")]
264 cmd.append(
"-model_chain1")
266 cmd.append(
"-model_chain2")
268 cmd.append(
"-native_chain1")
270 cmd.append(
"-native_chain2")
273 proc = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
275 shutil.rmtree(tmp_dir)
277 if proc.returncode != 0:
278 raise RuntimeError(
"DockQ run failed - returncode: " + \
279 str(proc.returncode) +
", stderr: " + \
280 proc.stderr.decode() +
", stdout: " + \
281 proc.stdout.decode())
283 if proc.stderr.decode() !=
"":
284 raise RuntimeError(
"DockQ run failed - stderr: " + \
285 proc.stderr.decode() +
", stdout: " + \
286 proc.stdout.decode())
288 return DockQResult.FromDockQOutput(proc.stdout.decode())