Source code for modelcif.qa_metric
"""Classes to annotate models with quality scores.
To use, first declare a class for the desired score by deriving
from both a subclass of :class:`MetricMode` (which defines the part
of the system the metric applies to) and a subclass of :class:`MetricType`
(which describes the meaning of the score value). Set the ``software``
attribute to point to the software used to calculate the metric
(as a :class:`modelcif.SoftwareGroup` or :class:`modelcif.Software` object).
For example to declare a global distance score::
class MyScore(modelcif.qa_metric.Global, modelcif.qa_metric.Distance):
"My distance-based quality score"
software = modelcif.Software(...)
The name and description of the score in the mmCIF file will be taken from
the name and docstring of the Python class, unless the
:attr:`MetricMode.name` or :attr:`MetricMode.description` attributes are
overridden in the subclass.
QA metric objects should be added to
:attr:`modelcif.model.Model.qa_metrics`.
"""
[docs]
class MetricMode(object):
"""Base class for the mode of a quality metric.
Use a derived class such as :class:`Global`, :class:`Local`,
or :class:`LocalPairwise` for declaring a new score.
"""
name = property(lambda x: type(x).__name__,
doc="Short name of this score. By default it is just the "
"class name, but this can be overridden in subclasses "
"(for example to create names containing spaces).")
description = property(lambda x: x.__doc__.split("\n")[0],
doc="Longer text description of this score. By "
"default it is the first line of the "
"docstring.")
[docs]
class Global(MetricMode):
"""A score that is calculated per-model.
:param float value: The score value (see :class:`MetricType`).
"""
mode = "global"
def __init__(self, value):
self.value = value
def __repr__(self):
return "<%s(value=%r)>" % (type(self).__name__, self.value)
[docs]
class Local(MetricMode):
"""A score that is calculated on a single residue.
:param residue: The residue that is scored.
:type residue: :class:`modelcif.Residue`
:param float value: The score value (see :class:`MetricType`).
"""
mode = "local"
def __init__(self, residue, value):
self.residue = residue
self.value = value
def __repr__(self):
return "<%s(residue=%r, value=%r)>" % (type(self).__name__,
self.residue, self.value)
[docs]
class LocalPairwise(MetricMode):
"""A score that is calculated between two residues.
:param residue1: The first residue that is scored.
:type residue1: :class:`modelcif.Residue`
:param residue2: The second residue that is scored.
:type residue2: :class:`modelcif.Residue`
:param float value: The score value (see :class:`MetricType`).
"""
mode = "local-pairwise"
def __init__(self, residue1, residue2, value):
self.residue1 = residue1
self.residue2 = residue2
self.value = value
def __repr__(self):
return ("<%s(residue1=%r, residue2=%r, value=%r)>"
% (type(self).__name__, self.residue1, self.residue2,
self.value))
[docs]
class MetricType(object):
"""Base class for the type of a quality metric.
Generally a derived class such as :class:`ZScore` or :class:`Distance`
is used to declare a new score, but a custom type can also be declared
by deriving from this class and providing a docstring to describe
the metric type::
class MPQSMetricType(modelcif.qa_metric.MetricType):
"composite score, values >1.1 are reliable"
"""
type = "other"
def _get_other_details(self):
# Find most derived class of MetricType before we pulled in MetricMode
# and use the first line of its docstring as other_details
if self.type == MetricType.type:
for base in type(self).mro():
if (issubclass(base, MetricType)
and base is not MetricType
and not issubclass(base, MetricMode)):
return base.__doc__.split('\n')[0]
other_details = property(
_get_other_details,
doc="More information about this metric type. By default it is the "
"first line of the MetricType subclass docstring.")
[docs]
class ZScore(MetricType):
"""Score that is the number of standard deviations from optimal/best.
See :class:`MetricType` for more information."""
type = "zscore"
other_details = None
[docs]
class Energy(MetricType):
"""Energy score (the lower the energy, the better the quality).
See :class:`MetricType` for more information."""
type = "energy"
other_details = None
[docs]
class Distance(MetricType):
"""Distance score (the lower the distance, the better the quality).
See :class:`MetricType` for more information."""
type = "distance"
other_details = None
[docs]
class NormalizedScore(MetricType):
"""Normalized score ranging from 0 to 1.
See :class:`MetricType` for more information."""
type = "normalized score"
other_details = None
[docs]
class PAE(MetricType):
"""Score that is a predicted aligned error.
See :class:`MetricType` for more information."""
type = "PAE"
other_details = None
[docs]
class PLDDT(MetricType):
"""Predicted lDDT-CA score in [0,100] (higher score, means better
accuracy). See :class:`MetricType` for more information."""
type = "pLDDT"
other_details = None
[docs]
class PTM(MetricType):
"""Predicted TM-score in [0,1] (higher value means higher confidence).
See :class:`MetricType` for more information."""
type = "pTM"
other_details = None
[docs]
class IpTM(MetricType):
"""Protein-protein interface score, based on TM-score in [0,1].
See :class:`MetricType` for more information."""
type = "ipTM"
other_details = None