def test_sasa_two_spheres(): 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(VectorXYZ([a, b]), 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_calc_mass_center(): from pyxmolpp2.geometry import calc_mass_center, XYZ, VectorXYZ, calc_rmsd, Rotation3d, Translation3d, Degrees import numpy as np a = VectorXYZ([XYZ(0, 1, 0), XYZ(1, 0, 0), XYZ(-1, 0, 0), XYZ(0, -1, 0)]) m = np.random.random((len(a), )).tolist() x = calc_mass_center(a, m) cm = sum([r * M for r, M in zip(a, m)], XYZ(0, 0, 0)) / np.sum(m) assert (x - cm).len() == pytest.approx(0)
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_inertia_tensor(): from pyxmolpp2.geometry import calc_inertia_tensor, XYZ, VectorXYZ, calc_rmsd, Rotation3d, Translation3d, Degrees import numpy as np a = VectorXYZ([XYZ(0, 1, 0), XYZ(1, 0, 0), XYZ(-1, 0, 0), XYZ(0, -1, 0)]) x = calc_inertia_tensor(a) assert np.allclose(x, np.diag([2, 2, 4])) m = [10, 1, 1, 10] x = calc_inertia_tensor(a, m) assert np.allclose(x, np.diag([20, 2, 22]))
def test_AtomSelection_transformations(): from pyxmolpp2.geometry import Translation3d, XYZ frame = make_polyglycine([("A", 20)]) ats = frame.asAtoms for a in ats: assert (a.r - XYZ(1,2,3)).len() == 0 transformation = Translation3d(XYZ(1,2,3)) ats.transform(transformation) for a in ats: assert (a.r - XYZ(2,4,6)).len() == 0
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_vectorXYZ_transformations(): v = VectorXYZ([XYZ(0, 0, 0), XYZ(1, 1, 1)]) v.transform(Translation3d(XYZ(2, 2, 2))) for (a, b) in zip(v, VectorXYZ([XYZ(2, 2, 2), XYZ(3, 3, 3)])): assert (a - b).len() == 0 v.transform(Translation3d(XYZ(2, 2, 2))) v.transform( Transformation3d(Rotation3d(XYZ(1, 1, 1), Degrees(30)), Translation3d(XYZ(2, 2, 2)))) v.transform(Rotation3d(XYZ(1, 1, 1), Degrees(30))) v.transform(UniformScale3d(5))
def test_calc_geom_center_exception(): from pyxmolpp2.geometry import calc_geom_center, XYZ, VectorXYZ, calc_rmsd, GeometryException, Transformation3d with pytest.raises(GeometryException): calc_geom_center(VectorXYZ([])) calc_geom_center(VectorXYZ([XYZ(1, 2, 3)]))
def test_autocorr(): from pyxmolpp2.geometry import XYZ, VectorXYZ, calc_autocorr_order_2 from numpy.random import random as rnd from timeit import default_timer as timer n = 1000 v = VectorXYZ([XYZ(rnd(), rnd(), rnd()) for i in range(n)]) v2 = [x.to_np for x in v] start = timer() cpp = calc_autocorr_order_2(v) end = timer() cpp_time = end - start start = timer() py = autocorr_all_harmonics(v2) end = timer() py_time = end - start py2 = autocorr_all_harmonics5(v2) assert np.max(np.abs([a - b for a, b in zip(cpp, py)])) < 1e-9 assert np.max(np.abs([a - b for a, b in zip(py2, py)])) < 1e-9 assert pytest.approx(1) == cpp[0] print("Time(c++) = %f" % cpp_time) print("Time(py) = %f" % py_time) print("Speedup = %g%%" % (py_time / cpp_time * 100))
def make_polyglycine( chain_lengths, no_reserve=True): from pyxmolpp2.polymer import Frame from pyxmolpp2.polymer import ChainName from pyxmolpp2.polymer import AtomName from pyxmolpp2.polymer import ResidueName, ResidueId from pyxmolpp2.geometry import XYZ aid=1 rid=1 frame = Frame(0) for chainId, N in chain_lengths: if no_reserve: c = frame.emplace(ChainName(chainId)) else: c = frame.emplace(ChainName(chainId),N) for i in range(N): if no_reserve: r = c.emplace(ResidueName("GLY"),ResidueId(rid)) else: r = c.emplace(ResidueName("GLY"),ResidueId(rid),7) rid+=1 for aname in ["N","H","CA","HA2","HA3","C","O"]: r.emplace(AtomName(aname),aid,XYZ(1,2,3)) aid+=1 return frame
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.to_np, as_np(a))
def test_composition(): from pyxmolpp2.geometry import calc_alignment, XYZ, VectorXYZ, calc_rmsd, Rotation3d, Translation3d, Degrees, UniformScale3d R = Rotation3d(XYZ(1, 1, 1), Degrees(39)) T = Translation3d(XYZ(7, 1, 2)) S = UniformScale3d(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_transformation_3d(): import numpy as np from pyxmolpp2.geometry import calc_alignment, XYZ, VectorXYZ, calc_rmsd, Rotation3d, Translation3d, Degrees, UniformScale3d R = Rotation3d(XYZ(1, 0, 0), Degrees(45)) T = Translation3d(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_Atom_setters(): from pyxmolpp2.polymer import AtomName from pyxmolpp2.geometry import XYZ frame = make_polyglycine([("A", 1)]) a = frame.asAtoms[0] a.name = AtomName("X") assert a.name == AtomName("X") a.aName = AtomName("Y") assert a.aName == AtomName("Y") a.id = 5 assert a.id == 5 a.aId = 7 assert a.aId == 7 a.r = XYZ(9,9,9) assert (a.r - XYZ(9,9,9)).len() == 0
def test_alignment_exception(): from pyxmolpp2.geometry import calc_alignment, XYZ, VectorXYZ, calc_rmsd, AlignmentError a = [XYZ(1, 2, 3)] * 10 with pytest.raises(AlignmentError): calc_alignment(VectorXYZ(a[:2]), VectorXYZ(a[:2])) calc_alignment(VectorXYZ(a[:3]), VectorXYZ(a[:3])) with pytest.raises(AlignmentError): calc_alignment(VectorXYZ(a[:4]), VectorXYZ(a))
def test_dihedral(): from pyxmolpp2.geometry import XYZ, dihedral_angle a = XYZ(1,0,0) b = XYZ(0,0,0) c = XYZ(0,0,1) d = XYZ(0,1,1) assert dihedral_angle(a,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 dihedral_angle(a,b,c,d).degrees == pytest.approx(45)
def test_sasa_three_spheres(): 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(VectorXYZ([a, b, c]), 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_calc_rmsd(): from pyxmolpp2.geometry import XYZ, AngleValue from pyxmolpp2.crystal import LatticeVectors, BestShiftFinder latticeVectors = LatticeVectors(XYZ(1, 4, 1), XYZ(5, 1, 1), XYZ(7, 1, 4)) bestShiftFinder = BestShiftFinder(latticeVectors) latticeVectors.scale_by(0.5) bestShiftFinder.scale_lattice_by(0.5) ref = XYZ(0, 0, 0) var = latticeVectors.translate(ref, 1, 4, 43) # print() # print(var.x,var.y,var.z) dr, shift = bestShiftFinder.find_best_shift(ref, var) # print(shift.x,shift.y,shift.z) var = var + shift assert var.x == pytest.approx(ref.x) assert var.y == pytest.approx(ref.y) assert var.z == pytest.approx(ref.z) assert dr == pytest.approx(0)
def test_calc_alignment(): from pyxmolpp2.geometry import calc_alignment, XYZ, VectorXYZ, calc_rmsd, Rotation3d, Translation3d, Degrees a = VectorXYZ([XYZ(1, 2, 3), XYZ(1, 2, 5), XYZ(4, 2, 7), XYZ(8, 1, 4)]) G = Rotation3d(XYZ(7, 6, 5), Degrees(12)) * Translation3d(XYZ(8, -9, 1)) b = VectorXYZ([G.transform(x) for x in a]) G2 = calc_alignment(a, b) assert calc_rmsd(a, b) > 1 assert calc_rmsd(a, b, G2) == pytest.approx(0)
def test_calc_rmsd_exception(): from pyxmolpp2.geometry import calc_alignment, XYZ, VectorXYZ, calc_rmsd, GeometryException, Transformation3d a = VectorXYZ([]) with pytest.raises(GeometryException): calc_rmsd(a, a) with pytest.raises(GeometryException): calc_rmsd(a, a, Transformation3d()) a = [XYZ(1, 2, 3)] * 10 with pytest.raises(GeometryException): calc_rmsd(VectorXYZ(a[:4]), VectorXYZ(a)) with pytest.raises(GeometryException): calc_rmsd(VectorXYZ(a[:4]), VectorXYZ(a), Transformation3d())
def test_calc_rmsd(): from pyxmolpp2.geometry import calc_alignment, XYZ, VectorXYZ, calc_rmsd a = VectorXYZ([XYZ(1, 2, 3)]) b = VectorXYZ([XYZ(3, 4, 5)]) assert calc_rmsd(a, b) == pytest.approx(math.sqrt(2**2 * 3)) a = VectorXYZ([XYZ(1, 2, 3), XYZ(1, 2, 3)]) b = VectorXYZ([XYZ(3, 4, 5), XYZ(1, 2, 3)]) assert calc_rmsd(a, b) == pytest.approx(math.sqrt(2**2 * 3 * 0.5))
def test_angle(): from pyxmolpp2.geometry import XYZ, angle a = XYZ(0,0,1) b = XYZ(0,0,0) c = XYZ(1,0,0) assert angle(a,b,c).degrees == pytest.approx(90) a = XYZ(0,0,1) b = XYZ(0,0,0) c = XYZ(1,0,1) assert angle(a,b,c).degrees == pytest.approx(45)
def test_vectorXYZ_numpy_conversions(): from timeit import default_timer as timer vectors = np.random.random((10000, 3)) start = timer() v1 = VectorXYZ([XYZ(x, y, z) for x, y, z in vectors]) end = timer() t1 = end - start start = timer() v2 = VectorXYZ.from_numpy(vectors) end = timer() t2 = end - start print("Time(py) = %f" % t1) print("Time(c++) = %f" % t2) print("Speedup = %g%%" % (t1 / t2 * 100)) assert np.allclose(vectors, v2.to_numpy())
def test_rotation_decomposition(): import numpy as np from pyxmolpp2.geometry import XYZ, Rotation3d, 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 = Rotation3d(ax, theta) ax1, theta1 = R.axis(), R.theta() R2 = Rotation3d(ax1, theta1) assert np.allclose(R.matrix3d(), R2.matrix3d()), ("\n".join( map(lambda x: "%25.18e" % x, (R.matrix3d() - R2.matrix3d()).flatten())))
def test_Frame(): from pyxmolpp2.polymer import Frame from pyxmolpp2.polymer import ChainName from pyxmolpp2.polymer import AtomName from pyxmolpp2.polymer import ResidueName, ResidueId from pyxmolpp2.geometry import XYZ f = Frame(5) c = f.emplace(ChainName("A"), 1) r = c.emplace(ResidueName("LYS"), ResidueId(1)) a = r.emplace(AtomName("CA"), 1, XYZ(1,2,3)) assert a.residue == r assert a.chain == c assert a.frame == f assert r.asAtoms[0] == a assert c.asAtoms[0] == a assert f.asAtoms[0] == a assert r.asAtoms.asResidues[0] == r assert c.asAtoms.asResidues[0] == r assert f.asAtoms.asResidues[0] == r assert r.asAtoms.asResidues.asChains[0] == c assert c.asAtoms.asResidues.asChains[0] == c assert f.asAtoms.asResidues.asChains[0] == c assert r.chain == c assert r.frame == f assert c.frame == f assert c.asResidues[0] == r assert f.asResidues[0] == r assert f.asChains[0] == c
def test_shorthands(): import numpy as np from pyxmolpp2.geometry import Rotation3d, Translation3d, XYZ, Degrees, calc_alignment frame = make_polyglycine([("A", 20)]) for a in frame.asAtoms: a.r = XYZ(*np.random.random(3)) frame2 = frame.copy() asel = frame.asAtoms asel2 = frame2.asAtoms asel.geom_center() asel.mass_center([1.0] * asel.size) asel.inertia_tensor([1.0] * asel.size) asel.geom_inertia_tensor() T = Translation3d(XYZ(1, 0, 0)) asel2.transform(T) assert np.isclose(asel.rmsd(asel2), 1.0) assert np.isclose(asel.rmsd(asel2.toCoords), 1.0) assert np.isclose(asel.rmsd(asel2.toCoords.transform(T.inverted())), 0.0) T = Translation3d(XYZ(1, 0, 0)) * Rotation3d(XYZ(1, 1, 1), Degrees(45)) asel.align_to(asel2) assert np.isclose(asel.rmsd(asel2), 0) asel2.transform(T) asel.align_to(asel2.toCoords) assert np.isclose(asel.rmsd(asel2), 0) T = Translation3d(XYZ(1, 0, 0)) * Rotation3d(XYZ(1, 1, 1), Degrees(45)) asel2.transform(T) assert np.allclose(T.matrix3d(), calc_alignment(asel2.toCoords, asel.toCoords).matrix3d()) assert np.allclose(T.matrix3d(), asel.alignment_to(asel2).matrix3d()) assert np.allclose(T.matrix3d(), asel.alignment_to(asel2.toCoords).matrix3d())
def check(G): r = XYZ(5, 6, 4) assert ((G * G.inverted()).transform(r) - r).len() == pytest.approx(0)
def test_distance(): from pyxmolpp2.geometry import XYZ, distance a = XYZ(1,2,3) b = XYZ(4,5,6) assert distance(a,b) == pytest.approx(math.sqrt((3**2 * 3)))
def translate_by_dr(a): #print(a,a.r) a.r = a.r+XYZ(1,2,3)