def test_rmsd_minimize(mol: molecule.Molecule) -> None: mol1 = copy.deepcopy(mol) mol2 = copy.deepcopy(mol) assert rmsd.rmsd(mol1.coordinates, mol2.coordinates, mol1.atomicnums, mol2.atomicnums) == pytest.approx(0) assert rmsd.rmsd( mol1.coordinates, mol2.coordinates, mol1.atomicnums, mol2.atomicnums, minimize=True, ) == pytest.approx(0) for _ in range(10): mol2.translate(np.random.rand(3)) mol2.rotate(np.random.rand(1), np.random.rand(3)) assert (rmsd.rmsd(mol1.coordinates, mol2.coordinates, mol1.atomicnums, mol2.atomicnums) > 0.0) assert rmsd.rmsd( mol1.coordinates, mol2.coordinates, mol1.atomicnums, mol2.atomicnums, minimize=True, ) == pytest.approx(0)
def test_rmsd_atol(i: int, j: int, result: float): """ Test usage of the :code:`atol` parameter for the QCP method. This parameter has been exposed to users following Issue 35 from @kjelljorner (https://github.com/RMeli/spyrmsd/issues/35) """ moli = copy.deepcopy(molecules.docking_2viz[i]) molj = copy.deepcopy(molecules.docking_2viz[j]) # Check results are different from 0.0 assert not result == pytest.approx(0.0) assert (rmsd.rmsd( moli.coordinates, molj.coordinates, moli.atomicnums, molj.atomicnums, minimize=True, ) == pytest.approx(result)) assert (rmsd.rmsd( moli.coordinates, molj.coordinates, moli.atomicnums, molj.atomicnums, minimize=True, atol=1e9, ) == pytest.approx(0.0))
def test_symmrmsd_rotated_benzene_stripped(angle: float) -> None: mol1 = copy.deepcopy(molecules.benzene) mol2 = copy.deepcopy(molecules.benzene) mol2.rotate(angle, np.array([0, 0, 1]), units="deg") mol1.strip() mol2.strip() assert (rmsd.rmsd(mol1.coordinates, mol2.coordinates, mol1.atomicnums, mol2.atomicnums) > 0) assert rmsd.rmsd( mol1.coordinates, mol2.coordinates, mol1.atomicnums, mol2.atomicnums, minimize=True, ) == pytest.approx(0) assert rmsd.hrmsd(mol1.coordinates, mol2.coordinates, mol1.atomicnums, mol2.atomicnums) == pytest.approx(0, abs=1e-4) assert rmsd.symmrmsd( mol1.coordinates, mol2.coordinates, mol1.atomicnums, mol2.atomicnums, mol1.adjacency_matrix, mol2.adjacency_matrix, ) == pytest.approx(0, abs=1e-4)
def test_rmsd_qcp_protein(i: int, rmsd_dummy: float, rmsd_min: float): mol0 = copy.deepcopy(molecules.trp[0]) mol = copy.deepcopy(molecules.trp[i]) assert rmsd.rmsd(mol0.coordinates, mol.coordinates, mol0.atomicnums, mol.atomicnums) == pytest.approx(rmsd_dummy) assert rmsd.rmsd( mol0.coordinates, mol.coordinates, mol0.atomicnums, mol.atomicnums, minimize=True, ) == pytest.approx(rmsd_min)
def test_rmsd_2viz(i: int, j: int, result: float) -> None: moli = copy.deepcopy(molecules.docking_2viz[i]) molj = copy.deepcopy(molecules.docking_2viz[j]) assert rmsd.rmsd(moli.coordinates, molj.coordinates, moli.atomicnums, molj.atomicnums) == pytest.approx(result)
def test_rmsd_centred_benzene() -> None: mol1 = copy.deepcopy(molecules.benzene) mol2 = copy.deepcopy(molecules.benzene) mol2.translate(np.array([0, 0, 1])) assert rmsd.rmsd(mol1.coordinates, mol2.coordinates, mol1.atomicnums, mol2.atomicnums) == pytest.approx(1) assert rmsd.rmsd( mol1.coordinates, mol2.coordinates, mol1.atomicnums, mol2.atomicnums, center=True, ) == pytest.approx(0)
def test_rmsd_hungarian_benzene_rotated(angle: float, tol: float) -> None: mol1 = copy.deepcopy(molecules.benzene) mol2 = copy.deepcopy(molecules.benzene) assert rmsd.rmsd(mol1.coordinates, mol2.coordinates, mol1.atomicnums, mol2.atomicnums) == pytest.approx(0) assert rmsd.hrmsd(mol1.coordinates, mol2.coordinates, mol1.atomicnums, mol2.atomicnums) == pytest.approx(0) # Rotations different than 180 degrees introduce numerical errors (~1e-6) mol2.rotate(angle, [0, 0, 1], units="deg") assert (rmsd.rmsd(mol1.coordinates, mol2.coordinates, mol1.atomicnums, mol2.atomicnums) > 0) assert rmsd.hrmsd(mol1.coordinates, mol2.coordinates, mol1.atomicnums, mol2.atomicnums) == pytest.approx(0, abs=tol)
def test_rmsd_benzene(t: float, RMSD: float) -> None: mol1 = copy.deepcopy(molecules.benzene) mol2 = copy.deepcopy(molecules.benzene) mol2.translate(np.array([0, 0, t])) assert rmsd.rmsd(mol1.coordinates, mol2.coordinates, mol1.atomicnums, mol2.atomicnums) == pytest.approx(RMSD)
def test_rmsd_qcp_2viz_stripped(i: int, j: int, result: float) -> None: moli = copy.deepcopy(molecules.docking_2viz[i]) molj = copy.deepcopy(molecules.docking_2viz[j]) # Strip hydrogen atoms moli.strip() molj.strip() assert rmsd.rmsd( moli.coordinates, molj.coordinates, moli.atomicnums, molj.atomicnums, minimize=True, ) == pytest.approx(result)
def test_symmrmsd_atomicnums_matching_pyridine_stripped() -> None: mol1 = copy.deepcopy(molecules.pyridine) mol2 = copy.deepcopy(molecules.pyridine) mol2.rotate(60, np.array([0, 0, 1]), units="deg") mol1.strip() mol2.strip() # Standard RMSD, correct in this case RMSD = rmsd.rmsd(mol1.coordinates, mol2.coordinates, mol1.atomicnums, mol2.atomicnums) # Isomorphic RMSD with atomic number matching is correct # Without atomic number matching this would be wrong because of higher symmetry assert rmsd.symmrmsd( mol1.coordinates, mol2.coordinates, mol1.atomicnums, mol2.atomicnums, mol1.adjacency_matrix, mol2.adjacency_matrix, ) == pytest.approx(RMSD, abs=1e-4)
def rmsdwrapper( molref, mols, symmetry: bool = True, center: bool = False, minimize: bool = False, strip: bool = True, cache: bool = True, ) -> Any: """ Compute RMSD between two molecule. Parameters ---------- mol1: molecule.Molecule Molecule 1 mol2: molecule.Molecule Molecule 2 symmetry: bool, optional Symmetry-corrected RMSD (using graph isomorphism) center: bool, optional Center molecules at origin minimize: bool, optional Minimised RMSD (using the quaternion polynomial method) strip: bool, optional Strip hydrogen atoms Returns ------- List[float] RMSDs """ if strip: molref.strip() for mol in mols: mol.strip() if minimize: center = True cref = coords_from_molecule(molref, center) cmols = [coords_from_molecule(mol, center) for mol in mols] RMSDlist = [] if symmetry: RMSDlist = rmsd.symmrmsd( cref, cmols, molref.atomicnums, mols[0].atomicnums, molref.adjacency_matrix, mols[0].adjacency_matrix, center=center, minimize=minimize, cache=cache, ) else: # No symmetry for c in cmols: RMSDlist.append( rmsd.rmsd( cref, c, molref.atomicnums, mols[0].atomicnums, center=center, minimize=minimize, )) return RMSDlist
time = [] rmsds = [] rmsd_nosymm = [] for ts in tqdm.tqdm(traj.trajectory[::step]): # Align protein backbones old_rmsd, new_rmsd = align.alignto(traj, ref, select="backbone", strict=True) assert new_rmsd <= old_rmsd if symmetry: r = rmsd.symmrmsd(selection.atoms.positions, ref_positions, atomicmap, atomicmap, A, A) else: r = rmsd.rmsd(selection.atoms.positions, ref_positions, atomicmap, atomicmap) time.append(ts.time) rmsds.append(r) rmsd_nosymm.append( rmsd.rmsd(selection.atoms.positions, ref_positions, atomicmap, atomicmap)) # Check rmsd_nosymm is the same as rms.RMDS rmsd_mda = rms.RMSD(traj, ref, select="backbone", groupselections=["resname LIG"], ref_frame=iframe) R = rmsd_mda.run(verbose=True, step=step)