Source code for prody.atomic.atomic

# -*- coding: utf-8 -*-
"""This module defines base class :class:`Atomic` that all other
:mod:`~prody.atomic` classes are derived from."""

from numpy import all, arange
from os import path
from prody import LOGGER, __path__
from prody.utilities import openData

from . import flags
from .bond import trimBonds
from .fields import READONLY

__all__ = ['Atomic', 'AAMAP']

NOTALLNONE = set(['not', 'all', 'none', 'index', 'sequence', 'x', 'y', 'z'])

MODMAP = {}
with openData('mod_res_map.dat') as f:
    for line in f:
        try:
            mod, aa = line.strip().split(' ')
            MODMAP[mod] = aa
        except:
            continue

AAMAP = {
    'ALA': 'A', 'ARG': 'R', 'ASN': 'N', 'ASP': 'D', 'CYS': 'C', 'GLN': 'Q',
    'GLU': 'E', 'GLY': 'G', 'HIS': 'H', 'ILE': 'I', 'LEU': 'L', 'LYS': 'K',
    'MET': 'M', 'PHE': 'F', 'PRO': 'P', 'SER': 'S', 'THR': 'T', 'TRP': 'W',
    'TYR': 'Y', 'VAL': 'V',
    'ASX': 'B', 'GLX': 'Z', 'SEC': 'U', 'PYL': 'O', 'XLE': 'J', '': '-'
}

# add bases
AAMAP.update({'ADE': 'a', 'THY': 't', 'CYT': 'c',
              'GUA': 'g', 'URA': 'u'})

# add reversed mapping
_ = {}
for aaa, a in AAMAP.items():
    _[a] = aaa
AAMAP.update(_)

# add modified AAs
MODAAMAP = {}
for mod, aa in MODMAP.items():
    if aa in AAMAP:
        MODAAMAP[mod] = AAMAP[aa]
AAMAP.update(MODAAMAP)

[docs]class Atomic(object): """Base class for all atomic classes that can be used for type checking.""" __slots__ = [] def __getattribute__(self, name): try: return object.__getattribute__(self, name) except AttributeError: if name.startswith('is') and self.isFlagLabel(name[2:]): return all(self._getFlags(name[2:])) else: if name == 'all': try: ag = self.getAtomGroup() except AttributeError: ag = self selstr = name return Selection(ag, arange(self.numAtoms()), 'all', self._acsi, unique=True) else: try: dummies = self.numDummies() except AttributeError: return Selection(ag, self.getIndices(), self.getSelstr(), self._acsi, unique=True) else: return AtomMap(ag, self.getIndices(), self._acsi, intarrays=True, dummies=dummies, title=self.getTitle()) elif name == 'none': return None elif self.isFlagLabel(name): try: ag = self.getAtomGroup() except AttributeError: ag = self selstr = name else: selstr = '({0}) and ({1})'.format(name, self.getSelstr()) try: dummies = self.numDummies() except AttributeError: indices = self._getSubset(name) if len(indices): return Selection(ag, indices, selstr, self._acsi, unique=True) else: return None else: indices = self._getSubset(name) if len(indices): return AtomMap(ag, indices, self._acsi, intarrays=True, dummies=dummies, title='Selection ' + repr(name) + ' from ' + str(self)) else: return None else: selstr = name items = name.split('_') word = items[0] if (self.isFlagLabel(word) or self.isDataLabel(word) or word in NOTALLNONE or isSelectionMacro(word)): selstr = ' '.join(items) return SELECT.select(self, selstr) raise AttributeError('{0} object has no attribute `{1}` and {2} ' 'is not a valid selection string' .format(self.__class__.__name__, name, repr(selstr))) def __getstate__(self): return dict([(slot, getattr(self, slot)) for slot in self.__class__.__slots__]) def __setstate__(self, state): for slot in self.__class__.__slots__: try: value = state[slot] except KeyError: pass else: setattr(self, slot, value)
[docs] def copy(self): """Returns a copy of atoms (and atomic data) in an :class:`.AtomGroup` instance.""" dummies = None indices = None readonly = False try: ag = self.getAtomGroup() except AttributeError: ag = self readonly = True new = AtomGroup(ag.getTitle()) else: indices = self.getIndices() new = AtomGroup(ag.getTitle() + ' ' + str(self)) try: dummies = self.numDummies() except AttributeError: pass else: if dummies: dummy = self.getFlags('dummy') mapped = self.getFlags('mapped') try: self.getIndex() except AttributeError: this = self else: this = self.all if self.numCoordsets(): new.setCoords(this.getCoordsets(), label=ag.getCSLabels()) for label in ag.getDataLabels(): if label in READONLY: if readonly: new._data[label] = this.getData(label) else: new.setData(label, this.getData(label)) #if readonly: # for label in READONLY: # data = this.getData(label) # if data is not None: # new._data[label] = data skip_flags = set() for label in ag.getFlagLabels(): if label in skip_flags: continue else: new._setFlags(label, this.getFlags(label)) skip_flags.update(flags.ALIASES.get(label, [label])) if dummies: new._setFlags('dummy', dummy) new._setFlags('mapped', mapped) bonds = ag._bonds bmap = ag._bmap if bonds is not None and bmap is not None: if indices is None: new._bonds = bonds.copy() new._bmap = bmap.copy() new._data['numbonds'] = ag._data['numbonds'].copy() elif dummies: if dummies: indices = indices[self._getMapping()] if len(set(indices)) == len(indices): new.setBonds(trimBonds(bonds, indices)) else: LOGGER.warn('Duplicate atoms in mapping, bonds are ' 'not copied.') else: bonds = trimBonds(bonds, indices) if bonds is not None: new.setBonds(bonds) return new
__copy__ = copy toAtomGroup = copy
[docs] def select(self, selstr, **kwargs): """Returns atoms matching *selstr* criteria. See :mod:`~.select` module documentation for details and usage examples.""" return SELECT.select(self, selstr, **kwargs)
[docs] def getTitle(self): """Returns title of the instance.""" try: ag = self.getAtomGroup() except AttributeError: ag = self return ag._title
[docs] def getSequence(self, **kwargs): """Returns one-letter sequence string for amino acids. When *allres* keyword argument is **True**, sequence will include all residues (e.g. water molecules) in the chain and **X** will be used for non-standard residue names.""" get = AAMAP.get if hasattr(self, 'getResnames'): seq = ''.join([get(res, 'X') for res in self.getResnames()]) else: res = self.getResname() seq = get(res, 'X') return seq
[docs] def toTEMPyAtoms(self): """Returns a BioPy.PDB Atom or Structure object as appropriate""" try: from TEMPy.protein.prot_rep_biopy import Atom as TEMPyAtom except ImportError: raise ImportError('TEMPy is needed for this functionality') if hasattr(self, 'getResnums'): return [atom.toTEMPyAtom() for atom in self if atom is not None] else: return [self.toTEMPyAtom()]
[docs] def toTEMPyStructure(self): """Returns a BioPy.PDB Atom or Structure object as appropriate""" try: from TEMPy.protein.prot_rep_biopy import BioPy_Structure except ImportError: raise ImportError('TEMPy is needed for this functionality') return BioPy_Structure(self.toTEMPyAtoms())