Source code for promod3.modelling._molprobity
'''Binding to external MolProbity tool to get scores.'''
import ost
from ost import settings
import subprocess, tempfile, os
[docs]def RunMolProbity(target_pdb, molprobity_bin=None):
'''Run ``MolProbity`` from ``Phenix`` on a given PDB file.
MolProbity score computation: (formula from molprobity source code)
.. code-block:: python
clashscore = result["Clashscore"]
rota_out = result["Rotamer outliers"]
rama_iffy = 100. - result["Ramachandran favored"]
mpscore = (( 0.426 * math.log(1 + clashscore) ) +
( 0.33 * math.log(1 + max(0, rota_out - 1)) ) +
( 0.25 * math.log(1 + max(0, rama_iffy - 2)) )) + 0.5
:param target_pdb: Path to PDB file on which to do analysis.
:type target_pdb: :class:`str`
:param molprobity_bin: Path to ``phenix.molprobity`` executable. If None, it
searches for it in the ``PATH`` or (if set) in the
env. variable ``MOLPROBITY_EXECUTABLE``.
The function was tested with ``Phenix 1.9-1692`` and
with ``MolProbity 4.2`` which also includes it.
:type molprobity_bin: :class:`str`
:return: Dictionary with scores produced by MolProbity. Entries:
- "Ramachandran outliers" (percentage [0,100] as :class:`float`)
- "Ramachandran favored" (percentage [0,100] as :class:`float`)
- "Rotamer outliers" (percentage [0,100] as :class:`float`)
- "C-beta deviations" (:class:`int`)
- "Clashscore" (:class:`float`)
- "MolProbity score" (:class:`float`)
- "RMS(bonds)" (:class:`float`)
- "RMS(angles)" (:class:`float`)
:rtype: :class:`dict`
:raises: :class:`~ost.settings.FileNotFound` if the "phenix.molprobity"
executable is not found.
'''
# HELPER
def GetStringValue(my_line):
"""Parse line formatted as ' bla = X ...' and return 'X' as string."""
return my_line.split('=')[1].strip().split(' ')[0]
# locate molprobity
molprobity_exec = settings.Locate("phenix.molprobity",
explicit_file_name=molprobity_bin,
env_name='MOLPROBITY_EXECUTABLE')
# run molprobity avoiding any file output
cmd = [molprobity_exec, target_pdb, "output.quiet=True", \
"output.coot=False", "output.probe_dots=False"]
job = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
sout, _ = job.communicate()
# parse
result = dict()
first_found = False
lines = sout.splitlines()
for line in lines:
my_line = line.strip().lower()
if my_line.startswith("ramachandran outliers"):
first_found = True
result["Ramachandran outliers"] = float(GetStringValue(line))
elif first_found and my_line.startswith("favored"):
result["Ramachandran favored"] = float(GetStringValue(line))
elif first_found and my_line.startswith("rotamer outliers"):
result["Rotamer outliers"] = float(GetStringValue(line))
elif first_found and my_line.startswith("clashscore"):
result["Clashscore"] = float(GetStringValue(line))
elif first_found and my_line.startswith("c-beta deviations"):
result["C-beta deviations"] = int(GetStringValue(line))
elif first_found and my_line.startswith("molprobity score"):
result["MolProbity score"] = float(GetStringValue(line))
elif first_found and my_line.startswith("rms(bonds)"):
result["RMS(bonds)"] = float(GetStringValue(line))
elif first_found and my_line.startswith("rms(angles)"):
result["RMS(angles)"] = float(GetStringValue(line))
return result
[docs]def RunMolProbityEntity(ost_ent, molprobity_bin=None):
'''Run molprobity from phenix on given OST entity.
See :func:`RunMolProbity` for details.
:param ost_ent: OST entity on which to do analysis.
:type ost_ent: :class:`Entity <ost.mol.EntityHandle>`
'''
# store as PDB in a tmp. file
_, tmpfile = tempfile.mkstemp(suffix='.pdb')
ost.PushVerbosityLevel(0)
ost.io.SavePDB(ost_ent, tmpfile)
ost.PopVerbosityLevel()
# get result
result = RunMolProbity(tmpfile, molprobity_bin)
# clean up
os.remove(tmpfile)
return result
[docs]def ReportMolProbityScores(scores):
'''Print MolProbity score and its components to LogInfo.
:param scores: MolProbity scores as generated by :func:`RunMolProbity`.
:type scores: :class:`dict`
'''
ost.LogInfo("MolProbity score: " + str(scores["MolProbity score"]))
ost.LogInfo("- Clashscore : " + str(scores["Clashscore"]))
ost.LogInfo("- Rotamer outliers : " + str(scores["Rotamer outliers"]) + " %")
ost.LogInfo("- Ramachandran favored: " + str(scores["Ramachandran favored"]) + " %")
__all__ = ('RunMolProbity', 'RunMolProbityEntity', 'ReportMolProbityScores')