####################################################################### 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 shouldnot be directly exposed to the user."""__author__="Christopher Woods"__email__="Christopher.Woods@bristol.ac.uk"__all__=["Bond"]fromsire.legacyimportMolas_SireMolfromsire.legacyimportMMas_SireMMfrom..import_isVerbosefrom._sire_wrapperimportSireWrapperas_SireWrapper
[docs]classBond(_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.ifisinstance(bond,_SireMM._MM.Bond):sire_object=bond# Another BioSimSpace Bond object.elifisinstance(bond,Bond):sire_object=bond._sire_object# Invalid type.else:raiseTypeError("'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."""ifnotisinstance(other,_Atom):raiseTypeError("'other' must be of type 'BioSimSpace._SireWrappers.Atom'.")# Return whether the bond contains the atom.returnself._sire_object.contains(other._sire_object.atom().number())def__getitem__(self,key):"""Get an atom from the bond."""# Slice.ifisinstance(key,slice):# Create a list to hold the atoms.atoms=[]# Iterate over the slice.forxinrange(*key.indices(2)):atoms.append(_Atom(self[x]))# Return the list of atoms.returnatoms# Index.else:try:key=int(key)except:raiseTypeError("'key' must be of type 'int'")ifkey<-2orkey>1:raiseIndexError("Residue index is out of range.")ifkey<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."""raiseTypeError("'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=0returnselfdef__next__(self):"""An iterator for the object."""# Stop if we've reached the end of the bond.ifself._iter_count==2:raiseStopIteration# Extract the next atom in the bond.atom=self[self._iter_count]# Update the iterator counter.self._iter_count+=1# Return the atom.returnatomdef__len__(self):"""Return the number of atoms in the bond."""return2
[docs]defatom0(self):""" Return the first atom in the bond. Returns ------- atom : Atom The atom """return_Atom(self._sire_object.atom0())
[docs]defatom1(self):""" Return the first atom in the bond. Returns ------- atom : Atom The atom """return_Atom(self._sire_object.atom1())
[docs]deflength(self):""" Return the length of the bond. Returns ------- length : :class:`Length <BioSimSpace.Types.Length>` The length of the bond """from..TypesimportLengthas_Lengthreturn_Length(self._sire_object.length())
[docs]defenergy(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..TypesimportEnergyas_Energyreturn_Energy(self._sire_object.energy())
[docs]defname(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]defmoleculeNumber(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. """returnself._sire_object.molecule().number().value()
[docs]defcoordinates(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=[]foratominself.getAtoms():coordinates.append(atom.coordinates(property_map))except:returnNone# Return the coordinates.returncoordinates
[docs]defnAtoms(self):""" Return the number of atoms in the bond. Returns ------- num_atoms : int The number of atoms in the system. """return2
[docs]defgetAtoms(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=[]foratominself._sire_object.atoms():atoms.append(_Atom(atom))returnatoms
[docs]deftoMolecule(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]defsearch(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") """ifnotisinstance(query,str):raiseTypeError("'query' must be of type 'str'")ifnotisinstance(property_map,dict):raiseTypeError("'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)exceptExceptionase:msg="'Invalid search query: %r"%queryif_isVerbose():raiseValueError(msg)fromeelse:raiseValueError(msg)fromNonereturn_SearchResult(search_result)
# Import at bottom of module to avoid circular dependency.from._atomimportAtomas_Atomfrom._moleculeimportMoleculeas_Moleculefrom._search_resultimportSearchResultas_SearchResult