"""
Implementation of sequence viewer Residue class.
Copyright Schrodinger, LLC. All rights reserved.
"""
# Contributors: Deacon Sweeney, PioStr Rotkiewicz
from past.utils import old_div
from . import constants
from . import utils
[docs]class Residue(object):
"""
This class implements a Residue, a basic sequence element. The Residue
object can correspond to an actual amino acid, nucleotide, or a single
plot point. It also stores associated Maestro metadata (such as atom
number or residue color).
"""
[docs] def __init__(self,
sequence=None,
code=' ',
ss_code='-',
name="UNK",
inverted=True,
color=(255, 255, 255)):
self.code = code # Single-letter residue code.
self.ss_code = ss_code # Secondary structure assignment.
self.name = name # PDB code
self.color = color # Foreground color.
self.inverted = inverted # Inverted color indicator.
self.selected = False
self.visible = True
self.value = 0.0 # Annotation value.
self.num = 0 # Res num. Same as PDB res num.
self.icode = ' ' # Residue insertion code.
self.sequence = sequence #Which residue belongs to.
self.is_gap = False # Gap indicator
self.tmp_code = None
self.avg_value = 0.0
self.previous_avg_value = 0.0 # Averaged value of previous residue.
self.next_avg_value = 0.0 # Averaged value of next residue.
self.profile_codes = []
# Maestro attributes.
self.maestro_atom_num = None
self.maestro_residue_index = -1 # Chain index
self.maestro_color = (32, 32, 32)
self.bfactor = 0 #Temperature factor
# Non-active residues are displayed in gray on a white background.
# Used to distinguish certain sequence regions.
self.active = True
self.composition = None #Amino acid composition in profile residues.
self.custom_color = None
self.structureless = True #Structure-less flag.
self.structure = [] #struct info read from PDB file.
self.model = False #marks template coverage for model building.
self.marked_color = None
self.area = 0.0 # Solvent accessible area
[docs] def copy(self):
"""
Creates a copy of self.
:rtype: `Residue`
:return: a copy of self
"""
new_residue = Residue()
new_residue.is_gap = self.is_gap
new_residue.sequence = self.sequence
new_residue.code = self.code
new_residue.num = self.num
new_residue.icode = self.icode
new_residue.color = self.color
new_residue.value = self.value
new_residue.avg_value = self.avg_value
new_residue.previous_avg_value = self.previous_avg_value
new_residue.next_avg_value = self.next_avg_value
new_residue.custom_color = self.custom_color
new_residue.structureless = self.structureless
new_residue.model = self.model
new_residue.marked_color = self.marked_color
new_residue.maestro_color = self.maestro_color
new_residue.composition = self.composition
new_residue.area = self.area
return new_residue
[docs] def id(self):
"""
Returns a residue ID. The residue ID is a string concatenating
the residue number and insertion code.
:rtype: string
:return: residue ID (number + insertion code)
"""
return str(self.num) + str(self.icode)
[docs] def makeName(self):
if self.code in constants.AMINO_ACIDS:
self.name = constants.AMINO_ACIDS[self.code][0]
else:
self.name = "UNK"
[docs] def colorTaylor(self):
"""
Returns a color according to Taylor scheme.
:rtype: (int, int, int)
:return: color according to Taylor scheme
"""
if self.is_gap:
return (0, 0, 0)
if self.code in list(constants.TAYLOR_SCHEME):
return constants.TAYLOR_SCHEME[self.code]
else:
return (255, 255, 255)
[docs] def colorType(self):
"""
Returns a color according to the residue type.
:rtype: (int, int, int)
:return: color according to residue type
"""
if self.is_gap:
return (0, 0, 0)
if self.code in list(constants.RES_TYPE_COLOR):
return constants.RES_TYPE_COLOR[self.code]
else:
return (255, 255, 255)
[docs] def colorKD(self):
"""
Returns a color according to Kyte-Doolittle hydrophobicity scale.
:rtype: (int, int, int)
:return: color according to hydrophobicity scale
"""
if self.is_gap:
return (0, 0, 0)
elif self.code in list(constants.HYDROPHOBICITY_SCALES):
value = (old_div(1.0, 4.5)) * (
constants.HYDROPHOBICITY_SCALES[self.code][constants.KD_SCALE])
return utils.colorGradientBlueWhiteRed(value)
else:
return (255, 255, 255)
[docs] def colorHW(self):
"""
Returns a color according to Hopp-Woods hydrophilicity scale.
:rtype: (int, int, int)
:return: color according to hydrophilicity scale
"""
if self.is_gap:
return (0, 0, 0)
elif self.code in list(constants.HYDROPHOBICITY_SCALES):
value = (old_div(1.0, 3.40)) * (
constants.HYDROPHOBICITY_SCALES[self.code][constants.HW_SCALE])
return utils.colorGradientBlueWhiteRed(value)
else:
return (255, 255, 255)
[docs] def colorHelixPropensity(self):
"""
Returns a color according to helix propensity.
:rtype: (int, int, int)
:return: color according to helix propensity
"""
if self.code in list(constants.HELIX_PROPENSITY_COLOR):
return constants.HELIX_PROPENSITY_COLOR[self.code]
else:
return (255, 255, 255) # Nonatural, gaps.
[docs] def colorStrandPropensity(self):
"""
Returns a color according to beta strand propensity.
:rtype: (int, int, int)
:return: color according to beta strand propensity
"""
if self.code in list(constants.BETA_STRAND_PROPENSITY_COLOR):
return constants.BETA_STRAND_PROPENSITY_COLOR[self.code]
else:
return (255, 255, 255)
[docs] def colorTurnPropensity(self):
"""
Returns a color according to turn propensity.
:rtype: (int, int, int)
:return: color according to turn propensity
"""
if self.code in list(constants.TURN_PROPENSITY_COLOR):
return constants.TURN_PROPENSITY_COLOR[self.code]
else:
return (255, 255, 255) # gaps, spaces
[docs] def colorHelixTerminators(self):
"""
Returns a color according to helix terminating tendency.
:rtype: (int, int, int)
:return: color according to helix terminating tendency
"""
if self.code in list(constants.HELIX_TERMINATION_TENDENCY_COLOR):
return constants.HELIX_TERMINATION_TENDENCY_COLOR[self.code]
else:
return (255, 255, 255) # Non-natural, gaps
[docs] def colorStericGroup(self):
"""
Returns a color according to steric group classification.
:rtype: (int, int, int)
:return: color according to steric group classification
"""
if self.code in list(constants.STERIC_GROUP_SCHEME):
return constants.STERIC_GROUP_SCHEME[self.code]
else:
return (255, 255, 255) # Non-natural, gaps
[docs] def colorExposureTendency(self):
"""
Returns a color according to solvent exposure tendency.
:rtype: (int, int, int)
:return: color according to solvent exposure tendency
"""
if self.code in list(constants.SOLVENT_EXPOSURE_TENDENCY_COLOR):
return constants.SOLVENT_EXPOSURE_TENDENCY_COLOR[self.code]
else:
return (255, 255, 255)
[docs] def colorSidechainChemistry(self):
"""
Returns a color according to sidechain chemistry.
:rtype: (int, int, int)
:return: color according to sidechain chemistry
"""
if self.code in list(constants.SIDECHAIN_CHEMISTRY_COLOR):
return constants.SIDECHAIN_CHEMISTRY_COLOR[self.code]
else:
return (255, 255, 255) # nonnatural, gaps
[docs] def repair(self):
"""
Repairs the residue by adding missing attributes (using
default values) to the residue.
"""
# Add missing attributes
empty_res = Residue()
for attr in list(empty_res.__dict__):
if not hasattr(self, attr):
setattr(self, attr, getattr(empty_res, attr))
[docs] def getSignature(self):
"""
This function returns residue signature.
:rtype: str
:return: Signature consisting of residue name, space,
chain_id, colon and residue number. If chain_id is
not available, space character is used instead.
"""
chain_id = ' '
if self.sequence:
chain_id = self.sequence.chain_id
return self.name[:3] + ' ' + chain_id + ':' + str(self.num)