Skip to content

Commit af1fb97

Browse files
committed
Initial orientations biased towards the restraints
1 parent a8258c2 commit af1fb97

File tree

3 files changed

+167
-22
lines changed

3 files changed

+167
-22
lines changed

lightdock/prep/poses.py

+80-18
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,43 @@ def get_random_point_within_sphere(number_generator, radius):
2525
if x**2 + y**2 + z**2 <= r2:
2626
return x, y, z
2727

28-
def get_quaternion_for_restraint(rec_residue, lig_residue, cx, cy, cz):
29-
"""Calculates the quaternion required for orienting the ligand towards the restraint"""
30-
r_ca = rec_residue.get_calpha()
31-
l_ca = lig_residue.get_calpha()
32-
a = np.array([r_ca.x, r_ca.y, r_ca.z])
33-
b = np.array([l_ca.x-cx, l_ca.y-cy, l_ca.z-cz])
28+
29+
def normalize_vector(v):
30+
norm = np.linalg.norm(v)
31+
if norm < 0.00001:
32+
return v
33+
return v / norm
34+
35+
36+
def orthogonal(v):
37+
"""Returns the orthogonal vector to v"""
38+
x = abs(v[0])
39+
y = abs(v[1])
40+
z = abs(v[2])
41+
if x < y:
42+
if x < z:
43+
other = np.array([1.0, 0.0, 0.0])
44+
else:
45+
other = np.array([0.0, 0.0, 1.0])
46+
else:
47+
if y < z:
48+
other = np.array([0.0, 1.0, 0.0])
49+
else:
50+
other = np.array([0.0, 0.0, 1.0])
51+
return np.cross(v, other)
52+
53+
54+
def quaternion_from_vectors(a, b):
55+
"""Calculate quaternion between two vectors a and b."""
56+
a = normalize_vector(a)
57+
b = normalize_vector(b)
58+
# Check for scenario where vectors are in the same direction
59+
if np.allclose(a, -b):
60+
o = orthogonal(a)
61+
return Quaternion(w=0., x=o[0], y=o[1], z=o[2])
3462
c = np.cross(a, b)
3563
d = np.dot(a, b)
36-
37-
try:
38-
s = np.sqrt( (1+d)*2 )
39-
except FloatingPointError:
40-
return Quaternion()
64+
s = np.sqrt( (1+abs(d))*2 )
4165
invs = 1. / s
4266
x = c[0] * invs
4367
y = c[1] * invs
@@ -47,19 +71,57 @@ def get_quaternion_for_restraint(rec_residue, lig_residue, cx, cy, cz):
4771
return Quaternion(w=w, x=x, y=y, z=z).normalize()
4872

4973

50-
def populate_poses(to_generate, center, radius, number_generator, rng_nm=None, rec_nm=0, lig_nm=0,
51-
receptor_restraints=None, ligand_restraints=None):
74+
def get_quaternion_for_restraint(rec_residue, lig_residue, tx, ty, tz, rt, lt):
75+
"""Calculates the quaternion required for orienting the ligand towards the restraint"""
76+
r_ca = rec_residue.get_calpha()
77+
l_ca = lig_residue.get_calpha()
78+
79+
rx = r_ca.x + rt[0]
80+
ry = r_ca.y + rt[1]
81+
rz = r_ca.z + rt[2]
82+
print rx, ry, rz
83+
84+
lx = l_ca.x + lt[0]
85+
ly = l_ca.y + lt[1]
86+
lz = l_ca.z + lt[2]
87+
print lx, ly, lz
88+
89+
# Define restraints vectors
90+
a = np.array([lx, ly, lz])
91+
b = np.array([rx - tx, ry - ty, rz - tz])
92+
93+
q = quaternion_from_vectors(a, b)
94+
#print q
95+
#print "***************"
96+
return q
97+
98+
99+
def populate_poses(to_generate, center, radius, number_generator, rec_translation, lig_translation,
100+
rng_nm=None, rec_nm=0, lig_nm=0, receptor_restraints=None, ligand_restraints=None):
52101
"""Creates new poses around a given center and a given radius"""
53102
new_poses = []
103+
104+
# Calculate closer residue restraints
105+
closest_residues = []
106+
if receptor_restraints:
107+
distances = []
108+
for i, residue in enumerate(receptor_restraints):
109+
ca = residue.get_calpha()
110+
distances.append((i, cdistance(ca.x , ca.y , ca.z ,
111+
center[0], center[1], center[2])))
112+
distances.sort(key=lambda tup: tup[1])
113+
closest_residues = [x[0] for x in distances[:10]]
114+
54115
for _ in xrange(to_generate):
55116
x, y, z = get_random_point_within_sphere(number_generator, radius)
56117
tx = center[0] + x
57118
ty = center[1] + y
58119
tz = center[2] + z
59120
if receptor_restraints and ligand_restraints:
60-
rec_residue = receptor_restraints[number_generator.randint(0, len(receptor_restraints)-1)]
121+
rec_residue = receptor_restraints[closest_residues[number_generator.randint(0, len(closest_residues)-1)]]
61122
lig_residue = ligand_restraints[number_generator.randint(0, len(ligand_restraints)-1)]
62-
q = get_quaternion_for_restraint(rec_residue, lig_residue, center[0], center[1], center[2])
123+
q = get_quaternion_for_restraint(rec_residue, lig_residue, tx, ty, tz,
124+
rec_translation, lig_translation)
63125
else:
64126
q = Quaternion.random(number_generator)
65127
op_vector = [tx, ty, tz, q.w, q.x, q.y, q.z]
@@ -172,7 +234,7 @@ def calculate_initial_poses(receptor, ligand, num_clusters, num_glowworms,
172234
# Populate new poses if needed
173235
if len(poses) < num_glowworms:
174236
needed = num_glowworms - len(poses)
175-
poses.extend(populate_poses(needed, swarm_centers[cluster_id], radius, rng))
237+
poses.extend(populate_poses(needed, swarm_centers[cluster_id], radius, rng, rec_translation, lig_translation))
176238

177239
# Save poses as pdb file
178240
pdb_file_name = os.path.join(dest_folder, '%s_%s.pdb' % (DEFAULT_PDB_STARTING_PREFIX, cluster_id))
@@ -186,8 +248,8 @@ def calculate_initial_poses(receptor, ligand, num_clusters, num_glowworms,
186248
create_bild_file(bild_file_name, poses)
187249
else:
188250
for cluster_id, cluster_center in enumerate(swarm_centers):
189-
poses = populate_poses(num_glowworms, cluster_center, radius, rng, rng_nm, rec_nm, lig_nm,
190-
receptor_restraints, ligand_restraints)
251+
poses = populate_poses(num_glowworms, cluster_center, radius, rng, rec_translation, lig_translation,
252+
rng_nm, rec_nm, lig_nm, receptor_restraints, ligand_restraints)
191253
# Save poses as pdb file
192254
pdb_file_name = os.path.join(dest_folder, '%s_%s.pdb' % (DEFAULT_PDB_STARTING_PREFIX, cluster_id))
193255
create_pdb_from_points(pdb_file_name, [[pose[0], pose[1], pose[2]] for pose in poses[:num_glowworms]])

lightdock/scoring/fastdfire/driver.py

+3-4
Original file line numberDiff line numberDiff line change
@@ -141,10 +141,9 @@ def __call__(self, receptor, receptor_coordinates, ligand, ligand_coordinates):
141141
self.potential.dfire_energy,
142142
receptor_coordinates, ligand_coordinates)
143143
# Code to consider contacts in the interface
144-
#perc_receptor_restraints = ScoringFunction.restraints_satisfied(receptor.restraints, set(interface_receptor))
145-
#perc_ligand_restraints = ScoringFunction.restraints_satisfied(ligand.restraints, set(interface_ligand))
146-
#return energy + perc_receptor_restraints * energy + perc_ligand_restraints * energy
147-
return energy
144+
perc_receptor_restraints = ScoringFunction.restraints_satisfied(receptor.restraints, set(interface_receptor))
145+
perc_ligand_restraints = ScoringFunction.restraints_satisfied(ligand.restraints, set(interface_ligand))
146+
return energy + perc_receptor_restraints * energy + perc_ligand_restraints * energy
148147

149148
# Needed to dynamically load the scoring functions from command line
150149
DefinedScoringFunction = DFIRE

lightdock/test/prep/test_poses.py

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
"""Tests for poses related module"""
2+
3+
import os
4+
import shutil
5+
import filecmp
6+
import numpy as np
7+
from nose.tools import assert_almost_equal
8+
from lightdock.prep.poses import normalize_vector, quaternion_from_vectors
9+
from lightdock.mathutil.cython.quaternion import Quaternion
10+
from lightdock.structure.complex import Complex
11+
from lightdock.pdbutil.PDBIO import parse_complex_from_file, create_pdb_from_points
12+
13+
14+
class TestPoses:
15+
16+
def setUp(self):
17+
self.path = os.path.dirname(os.path.realpath(__file__))
18+
self.test_path = self.path + '/scratch_poses/'
19+
try:
20+
shutil.rmtree(self.test_path)
21+
except:
22+
pass
23+
os.mkdir(self.test_path)
24+
self.golden_data_path = os.path.normpath(os.path.dirname(os.path.realpath(__file__))) + '/golden_data/'
25+
26+
def tearDown(self):
27+
try:
28+
shutil.rmtree(self.test_path)
29+
except:
30+
pass
31+
32+
def test_normalize_vector1(self):
33+
v = np.array([1., 0., 0.])
34+
e = np.array([1., 0., 0.])
35+
n = normalize_vector(v)
36+
assert np.allclose(n, e)
37+
38+
def test_normalize_vector2(self):
39+
v = np.array([4., 0., 0.])
40+
e = np.array([1., 0., 0.])
41+
n = normalize_vector(v)
42+
assert np.allclose(n, e)
43+
44+
def test_normalize_vector3(self):
45+
v = np.array([0., 0., 0.])
46+
e = np.array([0., 0., 0.])
47+
n = normalize_vector(v)
48+
assert np.allclose(n, e)
49+
50+
def test_normalize_vector4(self):
51+
v = np.array([2., -2., 0.])
52+
e = np.array([0.70710678, -0.70710678, 0.])
53+
n = normalize_vector(v)
54+
assert np.allclose(n, e)
55+
56+
def test_quaternion_from_vectors1(self):
57+
a = np.array([1., 0., 0.])
58+
b = np.array([1., 0., 0.])
59+
q = quaternion_from_vectors(a, b)
60+
e = Quaternion()
61+
assert e == q
62+
63+
def test_quaternion_from_vectors2(self):
64+
a = np.array([1., 0., 0.])
65+
b = np.array([2., 0., 0.])
66+
q = quaternion_from_vectors(a, b)
67+
e = Quaternion()
68+
assert e == q
69+
70+
def test_quaternion_from_vectors3(self):
71+
a = np.array([1., 0., 0.])
72+
b = np.array([0., 2., 0.])
73+
q = quaternion_from_vectors(a, b)
74+
# 90 degrees in Z axis
75+
e = Quaternion(w=0.70710678, x=0.00000000, y=0.00000000, z=0.70710678)
76+
assert e == q
77+
78+
def test_quaternion_from_vectors4(self):
79+
a = np.array([1., 0., 0.])
80+
b = np.array([-1., 0., 0.])
81+
q = quaternion_from_vectors(a, b)
82+
# Orthogonal rotation
83+
e = Quaternion(w=0., x=0.00000000, y=-1.0, z=0.)
84+
assert e == q

0 commit comments

Comments
 (0)