Source code for BioSimSpace._SireWrappers._bond

######################################################################
# BioSimSpace: Making biomolecular simulation a breeze!
#
# Copyright: 2017-2024
#
# Authors: Lester Hedges <lester.hedges@gmail.com>
#
# BioSimSpace is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BioSimSpace is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with BioSimSpace. If not, see <http://www.gnu.org/licenses/>.
#####################################################################

"""
A thin wrapper around Sire.MM.Bond. This is an internal package and should
not be directly exposed to the user.
"""

__author__ = "Christopher Woods"
__email__ = "Christopher.Woods@bristol.ac.uk"

__all__ = ["Bond"]

from sire.legacy import Mol as _SireMol
from sire.legacy import MM as _SireMM

from .. import _isVerbose

from ._sire_wrapper import SireWrapper as _SireWrapper


[docs] class Bond(_SireWrapper): """A class for storing a bond."""
[docs] def __init__(self, bond): """ Constructor. Parameters ---------- bond : Sire.MM.Bond, :class:`Bond <BioSimSpace._SireWrappers.Bond>` A Sire or BioSimSpace Bond object. """ # Check that the bond is valid. # A Sire Bond object. if isinstance(bond, _SireMM._MM.Bond): sire_object = bond # Another BioSimSpace Bond object. elif isinstance(bond, Bond): sire_object = bond._sire_object # Invalid type. else: raise TypeError( "'bond' must be of type 'Sire.MM.Bond' " "or 'BioSimSpace._SireWrappers.Bond'." ) # Call the base class constructor. super().__init__(sire_object) # Flag that this object holds multiple atoms. self._is_multi_atom = True # Store the atom indices in the bond. self._atom_idxs = [ self._sire_object.atom0().index(), self._sire_object.atom1().index(), ] # Initialise the iterator count. self._iter_count = 0
def __str__(self): """Return a human readable string representation of the object.""" return "<BioSimSpace.Bond: name=%r, length=%s, molecule=%d>" % ( self.name(), self.length(), self.moleculeNumber(), ) def __repr__(self): """Return a string showing how to instantiate the object.""" return "<BioSimSpace.Bond: name=%r, length=%s, molecule=%d>" % ( self.name(), self.length(), self.moleculeNumber(), ) def __contains__(self, other): """Return whether other is in self.""" if not isinstance(other, _Atom): raise TypeError("'other' must be of type 'BioSimSpace._SireWrappers.Atom'.") # Return whether the bond contains the atom. return self._sire_object.contains(other._sire_object.atom().number()) def __getitem__(self, key): """Get an atom from the bond.""" # Slice. if isinstance(key, slice): # Create a list to hold the atoms. atoms = [] # Iterate over the slice. for x in range(*key.indices(2)): atoms.append(_Atom(self[x])) # Return the list of atoms. return atoms # Index. else: try: key = int(key) except: raise TypeError("'key' must be of type 'int'") if key < -2 or key > 1: raise IndexError("Residue index is out of range.") if key < 0: key = key + 2 # Extract and return the corresponding atom. return _Atom(self._sire_object.atom(self._atom_idxs[key])) def __setitem__(self, key, value): """Set an atom in the bond.""" raise TypeError("'Bond' object does not support assignment.") def __iter__(self): """An iterator for the object.""" # Reset the iterator counter and return the object. self._iter_count = 0 return self def __next__(self): """An iterator for the object.""" # Stop if we've reached the end of the bond. if self._iter_count == 2: raise StopIteration # Extract the next atom in the bond. atom = self[self._iter_count] # Update the iterator counter. self._iter_count += 1 # Return the atom. return atom def __len__(self): """Return the number of atoms in the bond.""" return 2
[docs] def atom0(self): """ Return the first atom in the bond. Returns ------- atom : Atom The atom """ return _Atom(self._sire_object.atom0())
[docs] def atom1(self): """ Return the first atom in the bond. Returns ------- atom : Atom The atom """ return _Atom(self._sire_object.atom1())
[docs] def length(self): """ Return the length of the bond. Returns ------- length : :class:`Length <BioSimSpace.Types.Length>` The length of the bond """ from ..Types import Length as _Length return _Length(self._sire_object.length())
[docs] def energy(self): """ Return the energy of the bond. This assumes that an energy expression has been assigned to this bond. Returns ------- energy : :class:`Energy <BioSimSpace.Types.Energy>` The energy of the bond """ from ..Types import Energy as _Energy return _Energy(self._sire_object.energy())
[docs] def name(self): """ Return the name of the bond. Returns ------- name : str The name of the bond. """ return ( f"{self._sire_object.atom0().name().value()}=" f"{self._sire_object.atom1().name().value()}" )
[docs] def moleculeNumber(self): """ Return the number of the molecule to which this bond belongs. Returns ------- number : int The number of the molecule to which the bond belongs. """ return self._sire_object.molecule().number().value()
[docs] def coordinates(self, property_map={}): """ Return the coordinates of the atoms in the bond. Parameters ---------- property_map : dict A dictionary that maps system "properties" to their user defined values. This allows the user to refer to properties with their own naming scheme, e.g. { "charge" : "my-charge" } Returns ------- [coordinates] : [class:`Coordinate <BioSimSpace.Types.Coordinate>`] The coordinates of the atoms in the bond. """ # Get the "coordinates" property for each atom in the bond. try: coordinates = [] for atom in self.getAtoms(): coordinates.append(atom.coordinates(property_map)) except: return None # Return the coordinates. return coordinates
[docs] def nAtoms(self): """ Return the number of atoms in the bond. Returns ------- num_atoms : int The number of atoms in the system. """ return 2
[docs] def getAtoms(self): """ Return a list containing all of the atoms in the bond. Parameters ---------- Returns ------- atoms : [:class:`Atoms <BioSimSpace._SireWrappers.Atom>`] The list of atoms in the bond. """ atoms = [] for atom in self._sire_object.atoms(): atoms.append(_Atom(atom)) return atoms
[docs] def toMolecule(self): """ Convert a single Residue to a Molecule. Returns ------- system : :class:`Molecule <BioSimSpace._SireWrappers.Molecule>` """ return _Molecule( _SireMol.PartialMolecule(self._sire_object).extract().molecule() )
[docs] def search(self, query, property_map={}): """ Search the bond for atoms and bonds. Parameters ---------- query : str The search query. property_map : dict A dictionary that maps system "properties" to their user defined values. This allows the user to refer to properties with their own naming scheme, e.g. { "charge" : "my-charge" } Returns ------- results : [:class:`Atom <BioSimSpace._SireWrappers.Atom>`] A list of objects matching the search query. Examples -------- Search for all oxygen or hydrogen atoms. >>> result = bond.search("element oxygen or element hydrogen") Search for atom index 23. >>> result = bond.search("atomidx 23") """ if not isinstance(query, str): raise TypeError("'query' must be of type 'str'") if not isinstance(property_map, dict): raise TypeError("'property_map' must be of type 'dict'") # Initialise a list to hold the search results. results = [] try: # Query the Sire bond. search_result = _SireMol.Select(query)(self._sire_object, property_map) except Exception as e: msg = "'Invalid search query: %r" % query if _isVerbose(): raise ValueError(msg) from e else: raise ValueError(msg) from None return _SearchResult(search_result)
# Import at bottom of module to avoid circular dependency. from ._atom import Atom as _Atom from ._molecule import Molecule as _Molecule from ._search_result import SearchResult as _SearchResult