packmol-memgen-minimal 1.1.16__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- packmol_memgen/__init__.py +2 -0
- packmol_memgen/__version__.py +34 -0
- packmol_memgen/data/LICENSE.Apache-2.0 +201 -0
- packmol_memgen/data/extra_solvents.lib +789 -0
- packmol_memgen/data/frcmod.lipid_ext +97 -0
- packmol_memgen/data/frcmod.solvents +129 -0
- packmol_memgen/data/insane_lipids.txt +138 -0
- packmol_memgen/data/insane_solvents.txt +45 -0
- packmol_memgen/data/leaprc.extra_solvents +42 -0
- packmol_memgen/data/leaprc.lipid_ext +48 -0
- packmol_memgen/data/lipid_ext.lib +12312 -0
- packmol_memgen/data/martini_v3.0.0.itp +356605 -0
- packmol_memgen/data/memgen.parm +4082 -0
- packmol_memgen/data/pdbs.tar.gz +0 -0
- packmol_memgen/data/solvent.parm +14 -0
- packmol_memgen/example/example.sh +31 -0
- packmol_memgen/lib/__init__.py +0 -0
- packmol_memgen/lib/amber.py +77 -0
- packmol_memgen/lib/charmmlipid2amber/__init__.py +0 -0
- packmol_memgen/lib/charmmlipid2amber/charmmlipid2amber.csv +7164 -0
- packmol_memgen/lib/charmmlipid2amber/charmmlipid2amber.py +225 -0
- packmol_memgen/lib/pdbremix/LICENSE +21 -0
- packmol_memgen/lib/pdbremix/__init__.py +0 -0
- packmol_memgen/lib/pdbremix/_version.py +1 -0
- packmol_memgen/lib/pdbremix/amber.py +1103 -0
- packmol_memgen/lib/pdbremix/asa.py +227 -0
- packmol_memgen/lib/pdbremix/data/aminoacid.pdb +334 -0
- packmol_memgen/lib/pdbremix/data/binaries.json +26 -0
- packmol_memgen/lib/pdbremix/data/charmm22.parameter +2250 -0
- packmol_memgen/lib/pdbremix/data/charmm22.topology +1635 -0
- packmol_memgen/lib/pdbremix/data/color_b.py +682 -0
- packmol_memgen/lib/pdbremix/data/hin.lib +130 -0
- packmol_memgen/lib/pdbremix/data/hydroxide.lib +88 -0
- packmol_memgen/lib/pdbremix/data/make_chi.py +92 -0
- packmol_memgen/lib/pdbremix/data/opls.parameter +1108 -0
- packmol_memgen/lib/pdbremix/data/opls.topology +1869 -0
- packmol_memgen/lib/pdbremix/data/phd.frcmod +82 -0
- packmol_memgen/lib/pdbremix/data/phd.leaprc +4 -0
- packmol_memgen/lib/pdbremix/data/phd.prepin +35 -0
- packmol_memgen/lib/pdbremix/data/template.pdb +334 -0
- packmol_memgen/lib/pdbremix/data/znb.frcmod +24 -0
- packmol_memgen/lib/pdbremix/data/znb.leaprc +7 -0
- packmol_memgen/lib/pdbremix/data/znb.lib +69 -0
- packmol_memgen/lib/pdbremix/data.py +264 -0
- packmol_memgen/lib/pdbremix/fetch.py +102 -0
- packmol_memgen/lib/pdbremix/force.py +627 -0
- packmol_memgen/lib/pdbremix/gromacs.py +978 -0
- packmol_memgen/lib/pdbremix/lib/__init__.py +0 -0
- packmol_memgen/lib/pdbremix/lib/docopt.py +579 -0
- packmol_memgen/lib/pdbremix/lib/pyqcprot.py +305 -0
- packmol_memgen/lib/pdbremix/namd.py +1078 -0
- packmol_memgen/lib/pdbremix/pdbatoms.py +543 -0
- packmol_memgen/lib/pdbremix/pdbtext.py +120 -0
- packmol_memgen/lib/pdbremix/protein.py +311 -0
- packmol_memgen/lib/pdbremix/pymol.py +480 -0
- packmol_memgen/lib/pdbremix/rmsd.py +203 -0
- packmol_memgen/lib/pdbremix/simulate.py +420 -0
- packmol_memgen/lib/pdbremix/spacehash.py +73 -0
- packmol_memgen/lib/pdbremix/trajectory.py +286 -0
- packmol_memgen/lib/pdbremix/util.py +273 -0
- packmol_memgen/lib/pdbremix/v3.py +16 -0
- packmol_memgen/lib/pdbremix/v3array.py +482 -0
- packmol_memgen/lib/pdbremix/v3numpy.py +350 -0
- packmol_memgen/lib/pdbremix/volume.py +155 -0
- packmol_memgen/lib/utils.py +1017 -0
- packmol_memgen/main.py +2827 -0
- packmol_memgen_minimal-1.1.16.dist-info/METADATA +664 -0
- packmol_memgen_minimal-1.1.16.dist-info/RECORD +71 -0
- packmol_memgen_minimal-1.1.16.dist-info/WHEEL +4 -0
- packmol_memgen_minimal-1.1.16.dist-info/entry_points.txt +2 -0
- packmol_memgen_minimal-1.1.16.dist-info/licenses/LICENSE +338 -0
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
__doc__ = """
|
|
4
|
+
|
|
5
|
+
3D vector geometry library based on numpy.
|
|
6
|
+
|
|
7
|
+
The vectors and transform matrices are subclassd from numpy.array.
|
|
8
|
+
All operations are accessed through functions, allowing easy
|
|
9
|
+
switching with other libraries, such as v3array.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import math
|
|
13
|
+
import random
|
|
14
|
+
|
|
15
|
+
import numpy as np
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def vector(*args):
|
|
19
|
+
"""
|
|
20
|
+
Creates a new vector
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
None: returns zero vector
|
|
24
|
+
v (vector): returns copy of v
|
|
25
|
+
x, y, z: returns (x, y, z)
|
|
26
|
+
"""
|
|
27
|
+
n_arg = len(args)
|
|
28
|
+
if n_arg == 0:
|
|
29
|
+
return np.zeros(3, dtype=float)
|
|
30
|
+
if n_arg == 1:
|
|
31
|
+
data = args[0]
|
|
32
|
+
if len(data) == 3:
|
|
33
|
+
return np.array(data, copy=True)
|
|
34
|
+
raise TypeError('vector() with 1 argument must have 3 elements')
|
|
35
|
+
if n_arg == 3:
|
|
36
|
+
return np.array(args, dtype=float, copy=True)
|
|
37
|
+
else:
|
|
38
|
+
raise TypeError('vector() takes 0, 1 or 3 arguments')
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def set_vector(*args):
|
|
42
|
+
"""
|
|
43
|
+
Changes values of vector in place
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
v (vector), w (vector): copies values of w into v
|
|
47
|
+
v (vector), x, y, z: copiex x, y, z into v
|
|
48
|
+
"""
|
|
49
|
+
vector = args[0]
|
|
50
|
+
if len(args) == 2:
|
|
51
|
+
vector[:] = args[1]
|
|
52
|
+
elif len(args) == 4:
|
|
53
|
+
vector[:] = args[1:4]
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def mag(vector):
|
|
57
|
+
"""
|
|
58
|
+
Returns the magnitude of a vector
|
|
59
|
+
"""
|
|
60
|
+
return np.sqrt(np.dot(vector, vector))
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def mag2(vector):
|
|
64
|
+
"""
|
|
65
|
+
Returns square of the magnitude of a vector
|
|
66
|
+
"""
|
|
67
|
+
return np.dot(vector, vector)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def scale(vector, s):
|
|
71
|
+
"""
|
|
72
|
+
Returns vector that has been scaled by s.
|
|
73
|
+
"""
|
|
74
|
+
return s*vector
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
dot = np.dot
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def norm(vector):
|
|
81
|
+
"""
|
|
82
|
+
Returns vector normalized to magnitude=1.0
|
|
83
|
+
"""
|
|
84
|
+
return vector/mag(vector)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
cross = np.cross
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
radians = np.radians
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
degrees = np.degrees
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def identity():
|
|
97
|
+
"""
|
|
98
|
+
Returns the identity transform.
|
|
99
|
+
"""
|
|
100
|
+
return np.eye(4)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def matrix_elem(matrix, i, j, val=None):
|
|
104
|
+
"""
|
|
105
|
+
Reads/writes the elements of an affine transform.
|
|
106
|
+
|
|
107
|
+
1. 3x3 rotational component;
|
|
108
|
+
matrix_elem(m, i, j) for i=0..3, j=0..3
|
|
109
|
+
2. 3x1 translational component:
|
|
110
|
+
matrix_elem(m, 3, i) for i=0..3)
|
|
111
|
+
"""
|
|
112
|
+
if val is None:
|
|
113
|
+
return matrix[j,i]
|
|
114
|
+
else:
|
|
115
|
+
matrix[j,i] = val
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def transform(matrix, vector):
|
|
119
|
+
"""
|
|
120
|
+
Returns vector of applying the transform in matrix to v.
|
|
121
|
+
"""
|
|
122
|
+
# return np.dot(matrix[:3,:3], vector) + matrix[:3,3]
|
|
123
|
+
return np.dot(matrix, np.append(vector,[1],0))[:3]
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def left_inverse(matrix):
|
|
127
|
+
"""
|
|
128
|
+
Returns the left inverse of m.
|
|
129
|
+
|
|
130
|
+
Example:
|
|
131
|
+
combine(left_inverse(m), m) == identity().
|
|
132
|
+
"""
|
|
133
|
+
inverse = identity()
|
|
134
|
+
r = matrix[:3,:3].transpose()
|
|
135
|
+
inverse[:3,:3] = r
|
|
136
|
+
inverse[:3,3] = -np.dot(r, matrix[:3,3])
|
|
137
|
+
return inverse
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def rotation(axis, theta):
|
|
141
|
+
"""
|
|
142
|
+
Returns transform that rotate a vector at the origin around axis.
|
|
143
|
+
"""
|
|
144
|
+
# from http://stackoverflow.com/a/6802723
|
|
145
|
+
m = identity()
|
|
146
|
+
a = np.cos(theta/2)
|
|
147
|
+
b, c, d = norm(axis) * np.sin(theta/2)
|
|
148
|
+
m[0,:3] = [a*a+b*b-c*c-d*d, 2*(b*c-a*d), 2*(b*d+a*c) ]
|
|
149
|
+
m[1,:3] = [2*(b*c+a*d), a*a+c*c-b*b-d*d, 2*(c*d-a*b) ]
|
|
150
|
+
m[2,:3] = [2*(b*d-a*c), 2*(c*d+a*b), a*a+d*d-b*b-c*c]
|
|
151
|
+
return m
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def translation(displacement):
|
|
155
|
+
"""
|
|
156
|
+
Returns transform that translates a vector.
|
|
157
|
+
"""
|
|
158
|
+
m = identity()
|
|
159
|
+
m[:3,3] = displacement
|
|
160
|
+
return m
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def scaling_matrix(s0, s1, s2):
|
|
164
|
+
"""
|
|
165
|
+
Returns a scaling matrix.
|
|
166
|
+
"""
|
|
167
|
+
m = identity()
|
|
168
|
+
matrix_elem(m, 0, 0, s0)
|
|
169
|
+
matrix_elem(m, 1, 1, s1)
|
|
170
|
+
matrix_elem(m, 2, 2, s2)
|
|
171
|
+
return m
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def combine(m1, m2):
|
|
175
|
+
"""
|
|
176
|
+
Returns transform that combines two other transforms.
|
|
177
|
+
"""
|
|
178
|
+
return np.dot(m1, m2)
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def is_similar_mag(a, b, small=1E-5):
|
|
182
|
+
"""
|
|
183
|
+
Evaluates similar magnitudes to within small.
|
|
184
|
+
"""
|
|
185
|
+
return abs(abs(a)-abs(b)) <= small
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def is_similar_matrix(m1, m2, small=1E-5):
|
|
189
|
+
"""
|
|
190
|
+
Evaluates similar matrixes through matrix components.
|
|
191
|
+
"""
|
|
192
|
+
iter1 = np.ndenumerate(m1)
|
|
193
|
+
iter2 = np.ndenumerate(m2)
|
|
194
|
+
for (i1, val1), (i2, val2) in zip(iter1, iter2):
|
|
195
|
+
if not is_similar_mag(val1, val2, small):
|
|
196
|
+
return False
|
|
197
|
+
return True
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
is_similar_vector = is_similar_matrix
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
# common to v3list and v3numpy
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
def parallel(v, axis):
|
|
207
|
+
"""
|
|
208
|
+
Returns component of v parallel to axis.
|
|
209
|
+
"""
|
|
210
|
+
l = mag(axis)
|
|
211
|
+
if is_similar_mag(l, 0):
|
|
212
|
+
return v
|
|
213
|
+
else:
|
|
214
|
+
return scale(axis, dot(v, axis)/l/l)
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def perpendicular(v, axis):
|
|
218
|
+
"""
|
|
219
|
+
Returns component of v that is perpendicular to axis.
|
|
220
|
+
"""
|
|
221
|
+
return v - parallel(v, axis)
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
def normalize_angle(angle):
|
|
225
|
+
"""
|
|
226
|
+
Returns angle in radians that is [-pi, pi]
|
|
227
|
+
"""
|
|
228
|
+
while abs(angle) > math.pi:
|
|
229
|
+
if angle > math.pi:
|
|
230
|
+
angle -= math.pi*2
|
|
231
|
+
if angle < -math.pi:
|
|
232
|
+
angle += 2*math.pi
|
|
233
|
+
if is_similar_mag(abs(angle + math.pi), 0):
|
|
234
|
+
angle = math.pi
|
|
235
|
+
return angle
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def vec_angle(a, b):
|
|
239
|
+
"""
|
|
240
|
+
Returns angle in radians between a and b.
|
|
241
|
+
"""
|
|
242
|
+
a_len = mag(a)
|
|
243
|
+
b_len = mag(b)
|
|
244
|
+
if is_similar_mag(a_len, 0) or is_similar_mag(b_len, 0):
|
|
245
|
+
return 0.0
|
|
246
|
+
c = dot(a, b) / a_len / b_len
|
|
247
|
+
if c >= 1.0:
|
|
248
|
+
return 0.0
|
|
249
|
+
elif c <= -1.0:
|
|
250
|
+
return math.pi
|
|
251
|
+
else:
|
|
252
|
+
return math.acos(c)
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def vec_dihedral(a, axis, c):
|
|
256
|
+
"""
|
|
257
|
+
Returns dihedral angle between a and c, along the axis.
|
|
258
|
+
"""
|
|
259
|
+
ap = perpendicular(a, axis)
|
|
260
|
+
cp = perpendicular(c, axis)
|
|
261
|
+
angle = vec_angle(ap, cp)
|
|
262
|
+
if dot(cross(ap, cp), axis) > 0:
|
|
263
|
+
angle = -angle
|
|
264
|
+
return angle
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
def dihedral(p1, p2, p3, p4):
|
|
268
|
+
"""
|
|
269
|
+
Returns dihedral angle defined by the four positions.
|
|
270
|
+
"""
|
|
271
|
+
return vec_dihedral(p1-p2, p2-p3, p4-p3)
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
def distance(p1, p2):
|
|
275
|
+
"""
|
|
276
|
+
Returns distance between the two points
|
|
277
|
+
"""
|
|
278
|
+
return mag(p1 - p2)
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
def rotation_at_center(axis, theta, center):
|
|
282
|
+
"""
|
|
283
|
+
Returns a rotation around the center.
|
|
284
|
+
"""
|
|
285
|
+
t = translation(-center)
|
|
286
|
+
r = rotation(axis, theta)
|
|
287
|
+
t_inv = translation(center)
|
|
288
|
+
return combine(t_inv, combine(r, t))
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
def get_center(crds):
|
|
292
|
+
"""
|
|
293
|
+
Returns the geometric center of a bunch of positions.
|
|
294
|
+
"""
|
|
295
|
+
center = vector()
|
|
296
|
+
for crd in crds:
|
|
297
|
+
center += crd
|
|
298
|
+
return scale(center, 1.0/float(len(crds)))
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
def get_width(crds):
|
|
302
|
+
"""
|
|
303
|
+
Returns the maximum width between any two crds in the group.
|
|
304
|
+
"""
|
|
305
|
+
center = get_center(crds)
|
|
306
|
+
max_diff = 0
|
|
307
|
+
for crd in crds:
|
|
308
|
+
diff = v3.distance(crd, center)
|
|
309
|
+
if diff > max_diff:
|
|
310
|
+
max_diff = diff
|
|
311
|
+
return 2*max_diff
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
def random_mag():
|
|
315
|
+
"""
|
|
316
|
+
Returns a random positive number from [0, 90] for testing.
|
|
317
|
+
"""
|
|
318
|
+
return random.uniform(0, 90)
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
def random_real():
|
|
322
|
+
"""
|
|
323
|
+
Returns a random real +/- from [-90, 90] for testing.
|
|
324
|
+
"""
|
|
325
|
+
return random.uniform(-90, 90)
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
def random_vector():
|
|
329
|
+
"""
|
|
330
|
+
Returns a random vector for testing.
|
|
331
|
+
"""
|
|
332
|
+
return vector(random_real(), random_real(), random_real())
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
def random_rotation():
|
|
336
|
+
"""
|
|
337
|
+
Returns a random rotational matrix for testing.
|
|
338
|
+
"""
|
|
339
|
+
return rotation(random_vector(), radians(random_real()))
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
def random_matrix():
|
|
343
|
+
"""
|
|
344
|
+
Returns a random transformation matrix for testing.
|
|
345
|
+
"""
|
|
346
|
+
return combine(random_rotation(), translation(random_vector()))
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
__doc__ = """
|
|
4
|
+
Volume calculator for a list of atoms.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import math
|
|
8
|
+
import array
|
|
9
|
+
|
|
10
|
+
from . import pdbatoms
|
|
11
|
+
from . import v3
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Grid:
|
|
15
|
+
"""
|
|
16
|
+
Class to implement grid-point elimination.
|
|
17
|
+
|
|
18
|
+
A large grid of equidistant points is built. Functions are
|
|
19
|
+
provided to eliminate any points found within the radius of
|
|
20
|
+
a probe atom. The number of eliminated points is used to
|
|
21
|
+
estimate volume.
|
|
22
|
+
|
|
23
|
+
Attributes:
|
|
24
|
+
width (float)
|
|
25
|
+
center (vector)
|
|
26
|
+
spacing (float)
|
|
27
|
+
|
|
28
|
+
Methods:
|
|
29
|
+
__init__
|
|
30
|
+
reset
|
|
31
|
+
exclude_sphere
|
|
32
|
+
n_excluded
|
|
33
|
+
write_pdb
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
def __init__(self, grid_spacing, width, center):
|
|
37
|
+
self.width = float(width)
|
|
38
|
+
half_width = self.width / 2.0
|
|
39
|
+
self.center = v3.vector(center)
|
|
40
|
+
self.spacing = float(grid_spacing)
|
|
41
|
+
self.inv_spacing = 1.0 / self.spacing
|
|
42
|
+
|
|
43
|
+
self.n = 1
|
|
44
|
+
cover = 0
|
|
45
|
+
self.low = v3.vector()
|
|
46
|
+
while cover < half_width:
|
|
47
|
+
self.n += 1
|
|
48
|
+
half_n_point = int(self.n / 2)
|
|
49
|
+
self.low[0] = self.center[0] - half_n_point*self.spacing
|
|
50
|
+
self.low[1] = self.center[1] - half_n_point*self.spacing
|
|
51
|
+
self.low[2] = self.center[2] - half_n_point*self.spacing
|
|
52
|
+
width_1 = abs(self.center[0] - self.low[0])
|
|
53
|
+
high_x = self.low[0] + self.n*self.spacing
|
|
54
|
+
width_2 = abs(high_x - self.center[0])
|
|
55
|
+
cover = min(width_1, width_2)
|
|
56
|
+
|
|
57
|
+
self.actual_width = self.n*self.spacing
|
|
58
|
+
self.total_volume = self.actual_width**3
|
|
59
|
+
self.total_point = self.n**3
|
|
60
|
+
|
|
61
|
+
self.array = array.array('b')
|
|
62
|
+
for i in range(self.total_point):
|
|
63
|
+
self.array.append(0)
|
|
64
|
+
self.n_sq = self.n**2
|
|
65
|
+
|
|
66
|
+
self.x = [self.low[0] + i*self.spacing for i in range(self.n)]
|
|
67
|
+
self.y = [self.low[1] + j*self.spacing for j in range(self.n)]
|
|
68
|
+
self.z = [self.low[2] + k*self.spacing for k in range(self.n)]
|
|
69
|
+
|
|
70
|
+
def reset(self):
|
|
71
|
+
for i in range(self.total_point):
|
|
72
|
+
self.array[i] = 0
|
|
73
|
+
|
|
74
|
+
def indices(self, pos):
|
|
75
|
+
return ((pos[0]-self.low[0])*self.inv_spacing,
|
|
76
|
+
(pos[1]-self.low[1])*self.inv_spacing,
|
|
77
|
+
(pos[2]-self.low[2])*self.inv_spacing)
|
|
78
|
+
|
|
79
|
+
def pos(self, i, j, k):
|
|
80
|
+
return v3.vector(self.x[i], self.y[j], self.z[k])
|
|
81
|
+
|
|
82
|
+
def is_grid_point_near_sphere(self, i, j, k, pos, r_sq):
|
|
83
|
+
d_x = self.x[i] - pos[0]
|
|
84
|
+
d_y = self.y[j] - pos[1]
|
|
85
|
+
d_z = self.z[k] - pos[2]
|
|
86
|
+
return (d_x*d_x + d_y*d_y + d_z*d_z) < r_sq
|
|
87
|
+
|
|
88
|
+
def int_range(self, low_f, high_f):
|
|
89
|
+
low = max(0, int(math.floor(low_f-1)))
|
|
90
|
+
high = min(self.n, int(math.ceil(high_f) + 2))
|
|
91
|
+
return list(range(low, high))
|
|
92
|
+
|
|
93
|
+
def exclude_sphere(self, pos, r):
|
|
94
|
+
low = v3.vector(pos[0] - r, pos[1] - r, pos[2] - r)
|
|
95
|
+
low_i, low_j, low_k = self.indices(low)
|
|
96
|
+
high = v3.vector(pos[0] + r, pos[1] + r, pos[2] + r)
|
|
97
|
+
high_i, high_j, high_k = self.indices(high)
|
|
98
|
+
r_sq = r*r
|
|
99
|
+
for i in self.int_range(low_i, high_i):
|
|
100
|
+
for j in self.int_range(low_j, high_j):
|
|
101
|
+
for k in self.int_range(low_k, high_k):
|
|
102
|
+
l = i*self.n_sq + j*self.n + k
|
|
103
|
+
if self.array[l] == 0:
|
|
104
|
+
if self.is_grid_point_near_sphere(i, j, k, pos, r_sq):
|
|
105
|
+
self.array[l] = 1
|
|
106
|
+
|
|
107
|
+
def n_excluded(self):
|
|
108
|
+
return sum(self.array)
|
|
109
|
+
|
|
110
|
+
def write_pdb(
|
|
111
|
+
self, pdb, res_type="HOH", atom_type="O", element="O"):
|
|
112
|
+
i_res = 1
|
|
113
|
+
with open(pdb, 'w') as f:
|
|
114
|
+
for i in range(self.n):
|
|
115
|
+
for j in range(self.n):
|
|
116
|
+
for k in range(self.n):
|
|
117
|
+
l = i*self.n_sq + j*self.n + k
|
|
118
|
+
if self.array[l]:
|
|
119
|
+
atom = pdbatoms.Atom()
|
|
120
|
+
atom.pos = self.pos(i,j,k)
|
|
121
|
+
atom.type = atom_type
|
|
122
|
+
atom.is_hetatm = True
|
|
123
|
+
atom.element = element
|
|
124
|
+
atom.res_type = res_type
|
|
125
|
+
atom.res_num = i_res
|
|
126
|
+
atom.num = i_res
|
|
127
|
+
f.write(atom.pdb_str() + '\n')
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def volume(atoms, grid_spacing, pdb="", verbose=True):
|
|
131
|
+
"""
|
|
132
|
+
Returns the volume of a list of atoms, and writes a PDB file of
|
|
133
|
+
fictious atoms to fill the volume.
|
|
134
|
+
"""
|
|
135
|
+
center = pdbatoms.get_center(atoms)
|
|
136
|
+
width = pdbatoms.get_width(atoms, center) + 4.0
|
|
137
|
+
grid = Grid(grid_spacing, width, center)
|
|
138
|
+
if verbose:
|
|
139
|
+
print("%d atoms, grid %d x %d x %d points, width %.2f angstroms" % \
|
|
140
|
+
(len(atoms), grid.n, grid.n, grid.n, grid.actual_width))
|
|
141
|
+
for atom in atoms:
|
|
142
|
+
grid.exclude_sphere(atom.pos, atom.radius)
|
|
143
|
+
d_volume = float(grid_spacing)**3
|
|
144
|
+
volume = grid.n_excluded()*d_volume
|
|
145
|
+
if verbose:
|
|
146
|
+
print("Volume %.1f angstroms^3 (%d x %.3f angstroms^3)" \
|
|
147
|
+
% (volume, grid.n_excluded(), d_volume))
|
|
148
|
+
if pdb:
|
|
149
|
+
if verbose:
|
|
150
|
+
print("Warning: there will probably be more residues/atoms " \
|
|
151
|
+
"than PDB can uniquely number")
|
|
152
|
+
print(pdb)
|
|
153
|
+
grid.write_pdb(pdb)
|
|
154
|
+
return volume
|
|
155
|
+
|