Source code for schrodinger.application.desmond.fep_struc

"""Defines a `Struc` class as a generic represention of molecular structure
"""

import copy
import hashlib
import os

from schrodinger import adapter


[docs]class Struc(object): """ """
[docs] def __init__(self): # Public attributes: self.atom_prop = [] # Private attributes: self._id = None for i in range(len(self.atom) + 1): self.atom_prop.append({})
def __str__(self): return self.title() def _atom(self, index): """ Returns the index-th atom. """ raise NotImplementedError( "`_atom()' method not implemented by subclass")
[docs] def id(self): """ Returns the ID of this structure. """ if (self._id is None): self._id = hashlib.sha1(self.title()).hexdigest() return self._id
[docs] def set_id(self, id): """ Sets the ID for this structure. """ self._id = id
[docs] def copy(self): raise NotImplementedError("`copy' method not implemented by subclass")
[docs] def extract(self, indices): """ Return a new structure object which contains the atoms of the current structure that appear in the specified list. """ raise NotImplementedError( "`extract' method not implemented by subclass")
[docs] def title(self): raise NotImplementedError("`title' method not implemented by subclass")
[docs] def set_title(self, new_title): raise NotImplementedError( "`set_title' method not implemented by subclass")
[docs] def heavy_atoms(self): """ Returns a list of indices of heavy atoms (viz non-hydrogen atoms). """ raise NotImplementedError( "`heavy_atoms' method not implemented by subclass")
[docs] def is_chiral_atom(self, atom_index): """ Returns true if the atom indicated by `atom_index` is chiral; otherwise, false. :type atom_index: `int` :param atom_index: Atom index """ raise NotImplementedError( "`is_chiral_atom' method not implemented by subclass")
[docs] def chiral_atoms(self): """ Returns the indices of the chiral atoms. :rtype: `list` of `int` :return: A list of atom indices """ raise NotImplementedError( "`chiral_atoms' method not implemented by subclass")
[docs] def ring_atoms(self): """ Returns a set of ring atoms. :rtype: `set` of `int` :return: A set of atom indices """ raise NotImplementedError( "`ring_atom' method not implemented by subclass")
[docs] def bonded_atoms(self, atom_index): """ Returns a list of atom indices of atoms bonded to the indicated atom. :type atom_index: `int` :param atom_index: A single index or a list of indices of the atoms to be deleted :rtype: `list` of `int` :return: A list of atom indices of atoms bonded to the indicated atom """ raise NotImplementedError( "`bonded_atoms' method not implemented by subclass")
[docs] def total_charge(self): """ Returns the total charge of the structure. """ raise NotImplementedError( "`total_charge' method not implemented by subclass")
[docs] def delete_atom(self, atom_index): """ Deletes a atom. :type atom_index: `int` or `list` of `int` :param atom_index: A single index or a list of indices of the atoms to be deleted """ raise NotImplementedError( "`delete_atoms' method not implemented by subclass")
[docs] def smarts(self): """ Returns a SMARTS string of this structure. """ raise NotImplementedError("`smarts' method not implemented by subclass")
[docs] def smiles(self): """ Returns a SMILES string of this structure. """ raise NotImplementedError("`smiles' method not implemented by subclass")
[docs] def write(filename, format, mode="a"): """ Writes this structure into a file in the designated format. :type mode: `char`, 'a' | 'w' :param mode: When a file of the same name exists, this determines whether to overwrite ('w') or append ('a') to the file. """ raise NotImplementedError("`write' method not implemented by subclass")
[docs]class SchrodStruc(Struc): """ A `Struc` subclass based on Schrodinger's infrastructure """
[docs] def __init__(self, struc): """ `struc` should be a `schrodinger.structure.Structure` object. """ self._struc = struc # Public attributes: self.atom = self._struc.atom self.bond = self._struc.bond # Cached values: self._heavy_atom_cache = None Struc.__init__(self)
def __setstate__(self, dict): self.__dict__.update(dict) self.atom = self._struc.atom self.bond = self._struc.bond
[docs] def copy(self): """ Returns a copy of this structure. """ ret = SchrodStruc(self._struc.copy()) ret.atom_prop = copy.deepcopy(self.atom_prop) return ret
[docs] def extract(self, indices): """ Return a new structure object which contains the atoms of the current structure that appear in the specified list. """ ret = SchrodStruc(self._struc.extract(indices, True)) indices.sort() for i, e in enumerate(indices, start=1): ret.atom_prop[i] = copy.deepcopy(self.atom_prop[e]) return ret
[docs] def title(self): """ Returns the title of this structure. (Normally title's a user-friendly description) """ return self._struc.title
[docs] def set_title(self, new_title): """ Sets a new title to this structure. """ self._struc.title = new_title
[docs] def heavy_atoms(self): """ Returns a list of indices of heavy atoms (viz non-hydrogen atoms). """ if (self._heavy_atom_cache is None): ret = [] for e in self.atom: if (e.atomic_number > 1): ret.append(int(e)) else: ret = self._heavy_atom_cache return ret
[docs] def is_chiral_atom(self, atom_index): """ Returns true if the atom indicated by `atom_index` is chiral; otherwise, false. :type atom_index: `int` :param atom_index: Atom index """ return self._struc.atom[atom_index].chirality in [ "R", "S", "ANR", "ANS" ]
[docs] def chiral_atoms(self): """ Returns the indices of the chiral atoms. :rtype: `list` of `int` :return: A list of atom indices """ ret = [] for atom in self._struc.atom: if (atom.chirality in ["R", "S", "ANR", "ANS"]): ret.append(int(atom)) return ret
[docs] def ring_atoms(self, aromaticity=0, group=False): """ Returns ring atoms. :type aromaticity: `int` -1, 0, 1 :param aromaticity: -1 = non-aromatic, 0 = all, 1 = aromatic. Make the function return the specified type of ring atoms. :type group: `bool` :param group: If true, returns a list of `set` objects, each of which is a set of indices of atoms in the same ring; otherwise, returns a single set containing indices of all selected ring atoms. :rtype: `set` of `int` or a `list` of `set` of `int` :return: A set or a list of sets of atom indices """ ret = [] for e in self._struc.ring: if (aromaticity == 0 or (e.isAromatic() and aromaticity == 1) or (not e.isAromatic() and aromaticity == -1)): if (group): ret.append(set(e.getAtomIndices())) else: ret.extend(e.getAtomIndices()) return ret if (group) else set(ret)
[docs] def bonded_atoms(self, atom_index): """ Returns a list of atom indices of atoms bonded to the indicated atom. :type atom_index: `int` :param atom_index: A single index or a list of indices of the atoms to be deleted :rtype: `list` of `int` :return: A list of atom indices of atoms bonded to the indicated atom """ ret = [] for e in self._struc.atom[atom_index].bonded_atoms: ret.append(int(e)) return ret
[docs] def molecules(self): """ Returns a list of atom lists. Each element list is a list of atoms of a molecule in the structure. The first element in the returned list belongs to the biggest molecule. """ ret = [] for mol in self._struc.molecule: ret.append(mol.getAtomIndices()) def key_func(x): num_x = len(x) heavy_atoms = set(self.heavy_atoms()) num_heavy_in_x = len(set(x) - heavy_atoms) return num_x, num_heavy_in_x ret.sort(key=key_func, reverse=True) return ret
[docs] def total_charge(self): """ Returns the formal charge of the structure """ return self._struc.formal_charge
[docs] def add_hydrogens(self): """ Adds hydrogen atoms to this molecule. """ import schrodinger.structutils.build as build build.add_hydrogens(self._struc)
[docs] def delete_atom(self, atom_index): """ Deletes a atom. :type atom_index: `int` or `list` of `int` :param atom_index: A single index or a list of indices of the atoms to be deleted """ if (not isinstance(atom_index, list)): atom_index = [ atom_index, ] atom_index.sort() atom_index.reverse() self._struc.deleteAtoms(atom_index) for i in atom_index: del self.atom_prop[i] self._heavy_atom_cache = None
[docs] def smarts(self, atoms=None): """ Returns a SMARTS string for this structure. :type atoms: `list` of `int` :param atoms: A list of atom indices """ return adapter.to_smarts(self._struc, atoms)
[docs] def smiles(self): """ Returns a SMILES string for this structure. """ return adapter.to_smiles(self._struc)
[docs] def write(self, filename, format=None, mode="a", cil=False): """ Writes this structure into a file in the designated format. :type format: `str` or `None` :param format: If its value is `None`, the file format is determined from the filename suffix. If specified, it must be one of the following case-sensitive strings: "pdb", "mol2", "sd", "maestro", "smiles", and "smilescsv". """ if (cil): import time self._struc.property["r_fep_number"] = time.time() if ('a' == mode): if (os.path.isfile(filename)): self._struc.append(filename, format) else: self._struc.write(filename, format) elif ('w' == mode): self._struc.write(filename, format) else: raise ValueError( "Invalid value for `mode' argument: '%s', should be one of 'a' and 'w'." )