def test_sasa_two_spheres(): from pyxmolpp2 import calc_sasa for samples, precision in [ (10, 5e0), # 5% accuracy (50, 1e0), # 1% accuracy (250, 1e-1), # 0.1% accuracy (1000, 1e-2), # 0.01% accuracy (5000, 1e-3), # 0.001% accuracy ]: for _ in range(100): a = XYZ(*(np.random.random(3) * 2 - 1)) b = XYZ(*(np.random.random(3) * 2 - 1)) r1, r2 = np.random.random(2) * 2 + 0.01 S1 = 4 * np.pi * r1**2 S2 = 4 * np.pi * r2**2 S1_loss = first_sphere_hidden_area(a, b, r1, r2) S2_loss = first_sphere_hidden_area(b, a, r2, r1) total_area = S1 + S2 exposed_area_exact = total_area - S1_loss - S2_loss sasa = calc_sasa(np.array([a.values, b.values]), np.array([r1, r2]), 0, n_samples=samples) exposed_area_approx = sum(sasa) exposed_area_percent_exact = exposed_area_exact / total_area * 100 exposed_area_percent_approx = exposed_area_approx / total_area * 100 assert np.isclose(exposed_area_percent_exact, exposed_area_percent_approx, atol=precision)
def test_construction(): a = XYZ() b = XYZ(1, 2, 3) c = a + b assert c.x == 1 assert c.y == 2 assert c.z == 3
def test_calc_alignment(): from pyxmolpp2 import calc_alignment, XYZ, calc_rmsd, Rotation, Translation, Degrees a = np.array([(1, 2, 3), (1, 2, 5), (4, 2, 7), (8, 1, 4)]) G = Rotation(XYZ(7, 6, 5), Degrees(12)) * Translation(XYZ(8, -9, 1)) b = np.array([G.transform(XYZ(*x)).values for x in a]) G2 = calc_alignment(a, b) assert calc_rmsd(a, b) > 1 c = np.array([G2.transform(XYZ(*x)).values for x in b]) assert calc_rmsd(a, c) == pytest.approx(0)
def test_coord_span_assign_values(): from pyxmolpp2 import XYZ import numpy as np frame = make_polyglycine([("A", 10)]) frame.coords.values[:] = np.array([0, 0, 0]) assert frame.coords[0].distance(XYZ(0, 0, 0)) == pytest.approx(0) assert frame.coords[frame.coords.size - 1].distance(XYZ( 0, 0, 0)) == pytest.approx(0) frame.coords.values[:] = np.array([1, 2, 3]) assert frame.coords[0].distance(XYZ(1, 2, 3)) == pytest.approx(0) assert frame.coords[frame.coords.size - 1].distance(XYZ( 1, 2, 3)) == pytest.approx(0)
def test_AtomSelection_transformations(): from pyxmolpp2 import Translation, XYZ frame = make_polyglycine([("A", 20)]) ats = frame.atoms for a in ats: assert (a.r - XYZ(1, 2, 3)).len() == 0 transformation = Translation(XYZ(1, 2, 3)) ats.coords.apply(transformation) for a in ats: assert (a.r - XYZ(2, 4, 6)).len() == 0
def test_unit_cell_volume(): from pyxmolpp2 import UnitCell, XYZ, Degrees cell = UnitCell(1, 1, 1, Degrees(90), Degrees(90), Degrees(90)) assert cell.volume == 1 cell.scale_by(2) assert cell.volume == 8 cell.scale_to_volume(27) assert cell[0].distance(XYZ(3, 0, 0)) == pytest.approx(0) assert cell[1].distance(XYZ(0, 3, 0)) == pytest.approx(0) assert cell[2].distance(XYZ(0, 0, 3)) == pytest.approx(0)
def test_Atom_setters(): from pyxmolpp2 import XYZ frame = make_polyglycine([("A", 1)]) a = frame.atoms[0] a.name = "X" assert a.name == "X" a.id = 5 assert a.id == 5 a.r = XYZ(9, 9, 9) assert (a.r - XYZ(9, 9, 9)).len() == 0
def test_angle(): from pyxmolpp2 import XYZ a = XYZ(0, 0, 1) b = XYZ(0, 0, 0) c = XYZ(1, 0, 0) assert a.angle(b, c).degrees == pytest.approx(90) a = XYZ(0, 0, 1) b = XYZ(0, 0, 0) c = XYZ(1, 0, 1) assert a.angle(b, c).degrees == pytest.approx(45)
def test_operators(): import numpy as np def as_np(xyz): return np.array([xyz.x, xyz.y, xyz.z]) a = XYZ(5, 8, 1) a.x, a.y, a.z = 9, 8, 7 assert a.x == 9 assert a.y == 8 assert a.z == 7 b = XYZ(1, 2, 3) npa = as_np(a) npb = as_np(b) assert np.allclose(as_np(a + b), npa + npb) assert np.allclose(as_np(-a), -npa) assert np.allclose(as_np(a - b), npa - npb) assert np.allclose(as_np(a * 7), npa * 7) assert np.allclose(as_np(a / 7), npa / 7) assert np.allclose(as_np(7 * a), 7 * npa) assert np.allclose((a.dot(b)), np.dot(npa, npb)) assert np.allclose(a.len(), np.linalg.norm(npa)) assert np.allclose(a.len2(), np.linalg.norm(npa) ** 2) assert np.allclose(as_np(a.cross(b)), np.cross(npa, npb))
def test_pipes(): ref = PdbFile(os.environ["TEST_DATA_PATH"] + "/trjtool/GB1/run00001.pdb").frames()[0] traj = Trajectory(ref) traj.extend( TrjtoolDatFile(os.environ["TEST_DATA_PATH"] + "/trjtool/GB1/run00001.dat")) first_geom_center = XYZ(8.422286, 0.967190, -13.856332) for frame in traj: assert frame.coords.mean().distance(first_geom_center) < 0.001 break del frame for frame in traj | AngstromsToNanometers(): assert frame.coords.mean().distance(first_geom_center * 10) < 0.001 break del frame for frame in traj | Align(by=lambda a: True): assert frame.coords.mean().distance(first_geom_center) < 0.001 del frame for frame in traj[0:10] | Align(by=lambda a: True): assert frame.coords.mean().distance(first_geom_center) < 0.001 del frame for frame in traj[0:10] | Align( by=lambda a: True) | AngstromsToNanometers(): assert frame.coords.mean().distance(first_geom_center * 10) < 0.001 del frame
def __call__(self, frame: Frame): if not self.molecules_coords: self.molecules = [ mol for mol in frame.molecules.filter(self.molecules_selector) ] self.molecules_coords = [ mol.atoms.filter(self.reference_atoms_selector).coords for mol in self.molecules ] assert len(self.molecules_coords) == len( self.reference_mean_coords) assert frame.cell.volume > 1, "Did you forget to set periodic box?" # first molecule in assembly is aligned by convention alignment = self.ref_first_molecule_coords.alignment_to( self.molecules_coords[0]) # calculate reference coordinates for current frame ref_mean_coords = [ alignment.transform(r) for r in self.reference_mean_coords ] # shift rest of molecules to match reference coordinates as close as possible for mol_n in range(1, len(ref_mean_coords)): ref_point = ref_mean_coords[mol_n] mol = self.molecules[mol_n] mol_point = self.molecules_coords[mol_n].mean() closest = frame.cell.closest_image_to(ref_point, mol_point) if closest.shift.distance(XYZ()) > 0: mol.coords.apply(Translation(closest.shift)) return frame
def test_sasa_three_spheres(): from pyxmolpp2 import calc_sasa for samples, precision in [ (10, 5e0), # 5% accuracy (50, 1e0), # 1% accuracy (250, 1e-1), # 0.1% accuracy (1000, 1e-2), # 0.01% accuracy (5000, 1e-3), # 0.001% accuracy ]: for _ in range(100): r1, r2, r3 = np.random.random(3) * 2 + 0.01 a = XYZ(*(np.random.random(3) * 2 - 1)) b = XYZ(*(np.random.random(3) * 2 - 1)) v = XYZ(*np.random.random(3)) v /= v.len() c = a + v * (r1 + r3) S1 = 4 * np.pi * r1**2 S2 = 4 * np.pi * r2**2 S3 = 4 * np.pi * r3**2 S1_loss = first_sphere_hidden_area( a, b, r1, r2) + first_sphere_hidden_area(a, c, r1, r3) S2_loss = first_sphere_hidden_area( b, a, r2, r1) + first_sphere_hidden_area(b, c, r2, r3) S3_loss = first_sphere_hidden_area( c, a, r3, r1) + first_sphere_hidden_area(c, b, r3, r2) total_area = S1 + S2 + S3 exposed_area_exact = total_area - S1_loss - S2_loss - S3_loss sasa = calc_sasa(np.array([a.values, b.values, c.values]), np.array([r1, r2, r3]), 0, n_samples=samples) exposed_area_approx = sum(sasa) exposed_area_percent_exact = exposed_area_exact / total_area * 100 exposed_area_percent_approx = exposed_area_approx / total_area * 100 assert np.isclose(exposed_area_percent_exact, exposed_area_percent_approx, atol=precision), ( exposed_area_percent_exact, exposed_area_percent_approx, )
def test_Frame(): from pyxmolpp2 import Frame, ResidueId, XYZ f = Frame() c = f.add_molecule() c.name = "A" r = c.add_residue() r.name = "LYS" r.id = ResidueId(1) a = r.add_atom() a.name = "CA" a.id = 1 a.r = XYZ(1, 2, 3) a.mass = 14.25 a.vdw_radius = 7.5 assert a.r.distance(XYZ(1, 2, 3)) == 0 assert a.mass == 14.25 assert a.vdw_radius == 7.5 assert a.residue == r assert a.molecule == c assert a.frame == f assert r.atoms[0] == a assert c.atoms[0] == a assert f.atoms[0] == a assert r.atoms.residues[0] == r assert c.atoms.residues[0] == r assert f.atoms.residues[0] == r assert r.atoms.residues.molecules[0] == c assert c.atoms.residues.molecules[0] == c assert f.atoms.residues.molecules[0] == c assert r.molecule == c assert r.frame == f assert c.frame == f assert c.residues[0] == r assert f.residues[0] == r assert f.molecules[0] == c
def test_conversion(): import numpy as np def as_np(xyz): return np.array([xyz.x, xyz.y, xyz.z]) a = XYZ(5, 8, 1) assert np.allclose(a.values, as_np(a))
def test_closed_image(): from pyxmolpp2 import UnitCell, XYZ cell = UnitCell(XYZ(1, 4, 1), XYZ(5, 1, 1), XYZ(7, 1, 4)) cell.scale_by(0.5) ref = XYZ(0, 0, 0) var = ref + cell.translation_vector(1, 4, 43) # print() # print(var.x,var.y,var.z) result = cell.closest_image_to(ref, var) # print(shift.x,shift.y,shift.z) assert result.pos.x == pytest.approx(ref.x) assert result.pos.y == pytest.approx(ref.y) assert result.pos.z == pytest.approx(ref.z) assert result.distance == pytest.approx(0)
def test_transformation_3d(): import numpy as np from pyxmolpp2 import XYZ, Rotation, Translation, Degrees R = Rotation(XYZ(1, 0, 0), Degrees(45)) T = Translation(XYZ(1, 2, 5)) G = T * R m = G.matrix3d() v = G.vector3d() assert pytest.approx(m[0, 0]) == 1 assert pytest.approx(m[0, 1]) == 0 assert pytest.approx(m[0, 2]) == 0 assert pytest.approx(np.sqrt(2) / 2) == m[2, 1] assert v.x == 1 assert v.y == 2 assert v.z == 5
def test_composition(): from pyxmolpp2 import XYZ, Rotation, Translation, Degrees, UniformScale R = Rotation(XYZ(1, 1, 1), Degrees(39)) T = Translation(XYZ(7, 1, 2)) S = UniformScale(1.5) G = R * T * S * R * T def check(G): r = XYZ(5, 6, 4) assert ((G * G.inverted()).transform(r) - r).len() == pytest.approx(0) check(R) check(T) check(S) check(G) for a in [R, T, S, G]: for b in [R, T, S, G]: check(a * b)
def test_writer(): from pyxmolpp2 import PdbFile, XtcWriter, Translation, XYZ xtc_writer = XtcWriter("test.xtc", 1000) frame = PdbFile(os.environ["TEST_DATA_PATH"] + "/gromacs/xtc/1am7_protein.pdb").frames()[0] for i in range(10): frame.cell.scale_by(1.2) frame.coords.apply(Translation(XYZ(1, 0, 0))) xtc_writer.write(frame) del xtc_writer os.remove("test.xtc")
def test_to_tuple(): from pyxmolpp2 import UnitCell, XYZ cell = UnitCell(XYZ(1, 4, 1), XYZ(5, 1, 1), XYZ(7, 1, 4)) v1, v2, v3 = tuple(cell) assert v1.distance(XYZ(1, 4, 1)) == pytest.approx(0) assert v2.distance(XYZ(5, 1, 1)) == pytest.approx(0) assert v3.distance(XYZ(7, 1, 4)) == pytest.approx(0)
def test_calc_inertia_tensor_mass(): from pyxmolpp2 import Frame, XYZ import numpy as np frame = Frame() mol = frame.add_molecule() residue = mol.add_residue() for r, m in zip([(0, 1, 0), (1, 0, 0), (-1, 0, 0), (0, -1, 0)], [10, 1, 1, 10]): atom = residue.add_atom() atom.mass = m atom.r = XYZ(*r) assert np.allclose(frame.coords.inertia_tensor(), np.diag([2, 2, 4])) assert np.allclose(frame.atoms.inertia_tensor(), np.diag([20, 2, 22]))
def __call__(self, frame: Frame): # first molecule in assembly is aligned by convention alignment = self._ref_first_molecule_coords.alignment_to( self._molecules_coords[0]) # calculate reference coordinates for current frame ref_mean_coords = [ alignment.transform(r) for r in self._reference_mean_coords ] # shift rest of molecules to match reference coordinates as close as possible for mol_n in range(1, len(ref_mean_coords)): ref_point = ref_mean_coords[mol_n] mol = self._molecules[mol_n] mol_point = self._molecules_coords[mol_n].mean() closest = frame.cell.closest_image_to(ref_point, mol_point) if closest.shift.distance(XYZ()) > 0: mol.coords.apply(Translation(closest.shift)) return frame
def test_shorthands(): import numpy as np from pyxmolpp2 import Rotation, Translation, XYZ, Degrees, Frame, calc_alignment frame = make_polyglycine([("A", 20)]) for a in frame.atoms: a.r = XYZ(*np.random.random(3)) frame2 = Frame(frame) assert frame2 != frame print(frame, frame2) asel = frame.atoms asel2 = frame2.atoms asel.coords.mean() # asel.mass_center([1.0] * asel.size) # todo: enable # asel.inertia_tensor([1.0] * asel.size) # todo: enable asel.coords.inertia_tensor() T = Translation(XYZ(1, 0, 0)) asel2.coords.apply(T) print(asel.coords.rmsd(asel2.coords)) assert np.isclose(asel.coords.rmsd(asel2.coords), 1.0) assert np.isclose(asel.coords.rmsd(asel2.coords), 1.0) asel2.coords.apply(T.inverted()) assert np.isclose(asel.coords.rmsd(asel2.coords), 0.0) T = Translation(XYZ(1, 0, 0)) * Rotation(XYZ(1, 1, 1), Degrees(45)) asel.coords.apply(asel.coords.alignment_to(asel2.coords)) assert np.isclose(asel.coords.rmsd(asel2.coords), 0) asel2.coords.apply(T) asel.align_to(asel2) assert np.isclose(asel.coords.rmsd(asel2.coords), 0) asel2.coords.apply(T) asel2.guess_mass() asel.guess_mass() asel.align_to(asel2, weighted=True) assert np.isclose(asel.rmsd(asel2), 0) assert np.isclose(asel.rmsd(asel2, weighted=True), 0) T = Translation(XYZ(1, 0, 0)) * Rotation(XYZ(1, 1, 1), Degrees(45)) asel2.coords.apply(T) assert np.allclose( T.matrix3d(), calc_alignment(asel2.coords.values, asel.coords.values).matrix3d()) assert np.allclose(T.matrix3d(), asel.alignment_to(asel2).matrix3d())
def test_rotation_decomposition(): import numpy as np from pyxmolpp2 import XYZ, Rotation, Degrees for ax, theta in [ (XYZ(0, 0, 1), Degrees(30)), (XYZ(0, 0, 1), Degrees(70)), (XYZ(0, 1, 0), Degrees(70)), (XYZ(1, 0, 0), Degrees(70)), (XYZ(1, 1, 0), Degrees(70)), (XYZ(1, 1, 1), Degrees(70)), (XYZ(1, 0, 1), Degrees(0)), (XYZ(1, 1, 1), Degrees(0)), ]: R = Rotation(ax, theta) ax1, theta1 = R.axis(), R.theta() R2 = Rotation(ax1, theta1) assert np.allclose(R.matrix3d(), R2.matrix3d()), ("\n".join( map(lambda x: "%25.18e" % x, (R.matrix3d() - R2.matrix3d()).flatten())))
def make_polyglycine(chain_lengths): from pyxmolpp2 import Frame, XYZ, ResidueId aid = 1 rid = 1 frame = Frame() for chainId, N in chain_lengths: c = frame.add_molecule() c.name = chainId for i in range(N): r = c.add_residue() r.name = "GLY" r.id = ResidueId(rid) rid += 1 for aname in ["N", "H", "CA", "HA2", "HA3", "C", "O"]: a = r.add_atom() a.name = aname a.id = aid a.r = XYZ(1, 2, 3) aid += 1 return frame
def check(G): r = XYZ(5, 6, 4) assert ((G * G.inverted()).transform(r) - r).len() == pytest.approx(0)
def test_distance(): from pyxmolpp2 import XYZ a = XYZ(1, 2, 3) b = XYZ(4, 5, 6) assert a.distance(b) == pytest.approx(math.sqrt((3**2 * 3)))
def test_atoms_mean(): from pyxmolpp2 import XYZ, AtomSelection frame = make_polyglycine([("A", 1)]) frame.coords.values[:] = XYZ(4, 3, 7).values atoms = frame.atoms assert atoms.mean().distance(XYZ(4, 3, 7)) == 0 assert atoms.mean(weighted=True).distance(XYZ(4, 3, 7)) == 0 atoms[0].mass = 0 atoms[0].r = XYZ(1, 1, 1) assert atoms.mean(weighted=True).distance(XYZ(4, 3, 7)) == pytest.approx(0) assert atoms.mean(weighted=False).distance( (XYZ(4, 3, 7) * 6 + XYZ(1, 1, 1)) / 7) == pytest.approx(0) atoms = AtomSelection(frame.atoms) atoms[1].mass = 0 atoms[1].r = XYZ(1, 1, 1) assert atoms.mean(weighted=True).distance(XYZ(4, 3, 7)) == pytest.approx(0) assert atoms.mean(weighted=False).distance( (XYZ(4, 3, 7) * 5 + 2 * XYZ(1, 1, 1)) / 7) == pytest.approx(0)
def test_dihedral(): from pyxmolpp2 import XYZ a = XYZ(1, 0, 0) b = XYZ(0, 0, 0) c = XYZ(0, 0, 1) d = XYZ(0, 1, 1) assert a.dihedral(b, c, d).degrees == pytest.approx(90) a = XYZ(1, 0, 0) b = XYZ(0, 0, 0) c = XYZ(0, 0, 1) d = XYZ(1, 1, 1) assert a.dihedral(b, c, d).degrees == pytest.approx(45)
def translate_by_dr(a): # print(a,a.r) a.r = a.r + XYZ(1, 2, 3)