Tutorial
import spyrmsd
from spyrmsd import io, rmsd
RDKit
spyrmsd natively supports RDKit to load
molecules in order to work as a standalone tool. However, the API for
RMSD calculations is extremely minimal and only needs the following
information:
Atomic coordinates
Atomic numbers
Molecular adjacency matrix (for symmetry)
This means that spyrmsd can be used in combination with any library
that can provide such information.
Loading Molecules
The spyrmsd.io module provides functions to easily load molecules
from a file and to transform them into a spyrmsd.molecule.Molecule
object:
ref = io.loadmol("molecules/1a4k_ligand.sdf")
io.loadmol load a single molecule from a file. In order to load all
molecules we need to use io.loadallmols:
mols = io.loadallmols("molecules/1a4k_dock.sdf")
[22:16:58] Warning: molecule is tagged as 2D, but at least one Z coordinate is not zero. Marking the mol as 3D.
[22:16:58] Warning: molecule is tagged as 2D, but at least one Z coordinate is not zero. Marking the mol as 3D.
[22:16:58] Warning: molecule is tagged as 2D, but at least one Z coordinate is not zero. Marking the mol as 3D.
[22:16:58] Warning: molecule is tagged as 2D, but at least one Z coordinate is not zero. Marking the mol as 3D.
[22:16:58] Warning: molecule is tagged as 2D, but at least one Z coordinate is not zero. Marking the mol as 3D.
[22:16:58] Warning: molecule is tagged as 2D, but at least one Z coordinate is not zero. Marking the mol as 3D.
[22:16:58] Warning: molecule is tagged as 2D, but at least one Z coordinate is not zero. Marking the mol as 3D.
[22:16:58] Warning: molecule is tagged as 2D, but at least one Z coordinate is not zero. Marking the mol as 3D.
[22:16:58] Warning: molecule is tagged as 2D, but at least one Z coordinate is not zero. Marking the mol as 3D.
[22:16:58] Warning: molecule is tagged as 2D, but at least one Z coordinate is not zero. Marking the mol as 3D.
Loading RDKit Molecules
spyrmsd natively supports RDKit (if installed). The Molecule
class provides a from_rdkit() constructor.
from rdkit import Chem
from rdkit.Chem import AllChem
rdmol1 = Chem.MolFromSmiles("c1ccccc1")
rdmol2 = Chem.MolFromSmiles("c1ccccc1")
AllChem.EmbedMolecule(rdmol1)
AllChem.EmbedMolecule(rdmol2)
from spyrmsd.molecule import Molecule
from spyrmsd.rmsd import rmsdwrapper
mol1 = Molecule.from_rdkit(rdmol1)
mol2 = Molecule.from_rdkit(rdmol2)
rmsdwrapper(mol1, mol2)
[22:16:58] Molecule does not have explicit Hs. Consider calling AddHs()
[22:16:58] Molecule does not have explicit Hs. Consider calling AddHs()
[np.float64(0.12488387292807933)]
Removing Hydrogen Atoms
Hydrogen atoms can be removed with the strip() function:
ref.strip()
for mol in mols:
mol.strip()
Symmetry-Corrected RMSD
spyrmsd only needs atomic coordinates, atomic number and the
molecular adjacency matrix to compute the standard RMSD with
spyrmsd.rmsd.symmrmsd. The spyrmsd.molecule.Molecule class
provides easy access to such information:
coords_ref = ref.coordinates
anum_ref = ref.atomicnums
adj_ref = ref.adjacency_matrix
coords = [mol.coordinates for mol in mols]
anum = mols[0].atomicnums
adj = mols[0].adjacency_matrix
With this information we can easily compute the RMSD between the reference molecule and all other molecules:
RMSD = rmsd.symmrmsd(
coords_ref,
coords,
anum_ref,
anum,
adj_ref,
adj,
)
print(RMSD)
[np.float64(2.024608573240444), np.float64(1.4951562971486378), np.float64(10.028009301306854), np.float64(7.900570020309069), np.float64(7.578344354783399), np.float64(9.52999506817054), np.float64(4.952371789159666), np.float64(7.762808670066815), np.float64(9.996922964463582), np.float64(7.1732072690335755)]
Minimum RMSD
We can also compute the minimum RMSD obtained by superimposing the molecular structures:
RMSD = rmsd.symmrmsd(
coords_ref,
coords,
anum_ref,
anum,
adj_ref,
adj,
minimize=True,
)
print(RMSD)
[np.float64(1.2012368667355466), np.float64(1.0533413220699535), np.float64(1.153253104575548), np.float64(1.036542688936588), np.float64(0.8407673221224143), np.float64(1.1758143217869736), np.float64(0.7817315189656703), np.float64(1.0933314311267779), np.float64(1.0260767175206498), np.float64(0.9586369647000478)]
Change Backend
spyrmsd supports multiple backends. You see which backends are
available by looking at the available_backends attribute:
spyrmsd.available_backends
['rustworkx', 'networkx']
The available backends are a subset of the supported backends. Only the backends that are installed will be available.
You can check the current backend with
spyrmsd.get_backend()
'rustworkx'
You can switch the backend using
spyrmsd.set_backend("networkx")
spyrmsd.get_backend()
'networkx'