memprod 0.0.7__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.
- memprod/MemPrOD.py +1234 -0
- memprod/__init__.py +0 -0
- memprod-0.0.7.dist-info/METADATA +142 -0
- memprod-0.0.7.dist-info/RECORD +8 -0
- memprod-0.0.7.dist-info/WHEEL +5 -0
- memprod-0.0.7.dist-info/entry_points.txt +2 -0
- memprod-0.0.7.dist-info/licenses/LICENSE +674 -0
- memprod-0.0.7.dist-info/top_level.txt +1 -0
memprod/MemPrOD.py
ADDED
|
@@ -0,0 +1,1234 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
import warnings
|
|
4
|
+
import jax.numpy as jnp
|
|
5
|
+
from jax import tree_util
|
|
6
|
+
import jax
|
|
7
|
+
import jax.profiler
|
|
8
|
+
from enum import Enum
|
|
9
|
+
import numpy as np
|
|
10
|
+
from functools import partial
|
|
11
|
+
import matplotlib.pyplot as plt
|
|
12
|
+
import time
|
|
13
|
+
from mempro import MemPrO as ori
|
|
14
|
+
import argparse
|
|
15
|
+
from jax.sharding import PositionalSharding
|
|
16
|
+
from jax.experimental import mesh_utils
|
|
17
|
+
from scipy.optimize import minimize
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def main():
|
|
21
|
+
warnings.filterwarnings('ignore')
|
|
22
|
+
os.environ["TF_CPP_MIN_LOG_LEVEL"]="3"
|
|
23
|
+
jax.config.update("jax_enable_x64",True)
|
|
24
|
+
|
|
25
|
+
martini_default_path = os.environ["PATH_TO_MARTINI"]
|
|
26
|
+
|
|
27
|
+
#Reading command line args
|
|
28
|
+
parser = argparse.ArgumentParser(prog="MemPrOD",description="This is a program for the prediction of deformations caused by membrane proteins.")
|
|
29
|
+
parser.add_argument("-f", "--file_name",help = "Input file name (.pdb)")
|
|
30
|
+
parser.add_argument("-o","--output",help="Name of the output directory (Default: Deformations)")
|
|
31
|
+
parser.add_argument("-ni","--iters",help="Number of minimisation iterations (Default: 75)")
|
|
32
|
+
parser.set_defaults(iters=75)
|
|
33
|
+
parser.add_argument("-ng","--grid_density",help="Spacing of grid points (Default: 3)")
|
|
34
|
+
parser.set_defaults(grid_density=3)
|
|
35
|
+
parser.add_argument("-ncav","--no_cavity_surface",action="store_false",help="Toggle use of a surface finder that is more accurate but more expensive.")
|
|
36
|
+
parser.set_defaults(no_cavity_surface=True)
|
|
37
|
+
parser.add_argument("-itp","--itp_file",help="Path to force field (martini_v3.itp)")
|
|
38
|
+
parser.set_defaults(itp_file=martini_default_path)
|
|
39
|
+
parser.add_argument("-bd","--build_system",help = "Build a MD ready CG-system for ranks < n (Default: n=0)")
|
|
40
|
+
parser.set_defaults(build_system=False)
|
|
41
|
+
parser.add_argument("-bd_args","--build_arguments",help="Arguments to pass to insane when building system")
|
|
42
|
+
parser.set_defaults(build_arguments="")
|
|
43
|
+
parser.add_argument("-cut","--cutoff",help="Cutoff for LJ interactions (Deafult: 12)")
|
|
44
|
+
parser.set_defaults(cutoff=12)
|
|
45
|
+
parser.add_argument("-k1","--k1_const",help="Spring constant for neighbouring grid point Z deviations (Deafult: 0.25)")
|
|
46
|
+
parser.set_defaults(k1_const=0.25)
|
|
47
|
+
parser.add_argument("-k2","--k2_const",help="Spring constant for membrane compression (Deafult: 0)")
|
|
48
|
+
parser.set_defaults(k2_const=0)
|
|
49
|
+
parser.add_argument("-zshift","--zshift",help="Z shift of membrane for proteins that are missoriented due to lack of deformations.")
|
|
50
|
+
parser.set_defaults(zshift=0)
|
|
51
|
+
parser.add_argument("-mt","--membrane_thickness",help="Initial thickness of membrane in Angstroms (Deafult: 38)")
|
|
52
|
+
parser.set_defaults(membrane_thickness=38.0)
|
|
53
|
+
parser.add_argument("-wb","--write_bfactors",action="store_true",help="Toggle writing charge at each membrane segment instead of z position.")
|
|
54
|
+
parser.set_defaults(write_bfactors=False)
|
|
55
|
+
parser.add_argument("-res","--additional_residues",help="Comma seperate list of additional residues in input files (eg: POPG) Note the only ATOM entries will be read, all HETATM entries will be ignored.")
|
|
56
|
+
parser.set_defaults(additional_residues="")
|
|
57
|
+
parser.add_argument("-res_itp","--additional_residues_itp_file",help="Path to the itp file describing all additional residues, and bead types associated to beads in the residue. A CG representation is required, for atomisitic inputs an additional file is required which describes the beading.")
|
|
58
|
+
parser.set_defaults(additional_residues_itp_file="")
|
|
59
|
+
parser.add_argument("-res_cg","--residue_cg_file",help="Folder that contains a files of name RES.pdb describing the beading for each additional RES - see CG2AT github for examples")
|
|
60
|
+
parser.set_defaults(residue_cg_file="")
|
|
61
|
+
args = parser.parse_args()
|
|
62
|
+
|
|
63
|
+
#Error checking user inputs
|
|
64
|
+
add_reses = args.additional_residues.split(",")
|
|
65
|
+
if(len(add_reses) > 0):
|
|
66
|
+
if(len(add_reses[0]) > 0):
|
|
67
|
+
print("Using additional residues:",", ".join(add_reses))
|
|
68
|
+
if args.additional_residues_itp_file == "":
|
|
69
|
+
print("ERROR: Additional residue itp is required if using additional residues.")
|
|
70
|
+
exit()
|
|
71
|
+
if args.residue_cg_file == "":
|
|
72
|
+
print("WARNING: You have not added beading information for the added residues, this will cause an error if orienting a atomisitic input.")
|
|
73
|
+
|
|
74
|
+
if(len(add_reses) > 0):
|
|
75
|
+
if(len(add_reses[0]) > 0):
|
|
76
|
+
for i in add_reses:
|
|
77
|
+
ori.add_Reses(i,args.additional_residues_itp_file)
|
|
78
|
+
if len(args.residue_cg_file) > 0 :
|
|
79
|
+
ori.add_AtomToBeads(args.residue_cg_file.lstrip("/")+"/"+i+".pdb")
|
|
80
|
+
mem_data = [0,0]
|
|
81
|
+
|
|
82
|
+
try:
|
|
83
|
+
mem_data[1] = float(args.membrane_thickness)-10
|
|
84
|
+
except:
|
|
85
|
+
print("ERROR: Could not read value of -mt. Must be a float > 10.")
|
|
86
|
+
exit()
|
|
87
|
+
if(mem_data[1] <= 0):
|
|
88
|
+
print("ERROR: Could not read value of -mt. Must be a float > 10.")
|
|
89
|
+
exit()
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
try:
|
|
94
|
+
iters = int(args.iters)
|
|
95
|
+
except:
|
|
96
|
+
print("ERROR: Could not read value of -ni. Must be an integer >= 0.")
|
|
97
|
+
exit()
|
|
98
|
+
if(iters < 0):
|
|
99
|
+
print("ERROR: Could not read value of -ni. Must be an integer >= 0.")
|
|
100
|
+
exit()
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
try:
|
|
104
|
+
build_system = int(args.build_system)
|
|
105
|
+
except:
|
|
106
|
+
print("ERROR: Could not read value of -bd. Must be an integer > -1.")
|
|
107
|
+
exit()
|
|
108
|
+
if(build_system < 0):
|
|
109
|
+
print("ERROR: Could not read value of -bd. Must be an integer > -1.")
|
|
110
|
+
exit()
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
fn = args.file_name
|
|
115
|
+
|
|
116
|
+
if(not os.path.exists(fn)):
|
|
117
|
+
print("ERROR: Cannot find file: "+fn)
|
|
118
|
+
exit()
|
|
119
|
+
|
|
120
|
+
orient_dir = args.output
|
|
121
|
+
|
|
122
|
+
#Setting Martini itp file
|
|
123
|
+
martini_file = args.itp_file
|
|
124
|
+
|
|
125
|
+
if(not os.path.exists(martini_file)):
|
|
126
|
+
print("ERROR: Cannot find file: "+martini_file)
|
|
127
|
+
exit()
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
#Creating folders to hold data
|
|
131
|
+
if(orient_dir == None):
|
|
132
|
+
if(not os.path.exists("Deformations/")):
|
|
133
|
+
os.mkdir("Deformations/")
|
|
134
|
+
orient_dir = "Deformations/"
|
|
135
|
+
else:
|
|
136
|
+
if orient_dir[-1] != "/":
|
|
137
|
+
orient_dir += "/"
|
|
138
|
+
if(not os.path.exists(orient_dir)):
|
|
139
|
+
os.mkdir(orient_dir)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
locdir = orient_dir+"LocData/"
|
|
143
|
+
if(not os.path.exists(locdir)):
|
|
144
|
+
os.mkdir(locdir)
|
|
145
|
+
|
|
146
|
+
memdir = orient_dir+"Membrane_Data/"
|
|
147
|
+
if(not os.path.exists(memdir)):
|
|
148
|
+
os.mkdir(memdir)
|
|
149
|
+
|
|
150
|
+
timer = time.time()
|
|
151
|
+
tot_time = timer
|
|
152
|
+
|
|
153
|
+
#Some useful functions
|
|
154
|
+
|
|
155
|
+
@jax.jit
|
|
156
|
+
def flat_ind(ind1,ind2,max_ind1):
|
|
157
|
+
return ind2*max_ind1+ind1
|
|
158
|
+
@jax.jit
|
|
159
|
+
|
|
160
|
+
def unflat_ind(indf,max_ind1):
|
|
161
|
+
ind1 = indf%max_ind1
|
|
162
|
+
ind2 = jnp.array((indf-ind1)/max_ind1,dtype=int)
|
|
163
|
+
return ind1,ind2
|
|
164
|
+
|
|
165
|
+
@jax.jit
|
|
166
|
+
def put_into_grid(x,r,n,s):
|
|
167
|
+
cx = x[0]-s[0]
|
|
168
|
+
cy = x[1]-s[1]
|
|
169
|
+
norm_x = cx/r[0]
|
|
170
|
+
norm_y = cy/r[1]
|
|
171
|
+
grid_x = n[0]*norm_x
|
|
172
|
+
grid_y = n[1]*norm_y
|
|
173
|
+
return jnp.array(jnp.floor(grid_x),dtype=int),jnp.array(jnp.floor(grid_y),dtype=int)
|
|
174
|
+
|
|
175
|
+
twopowsixth = jnp.power(2,1/6)
|
|
176
|
+
|
|
177
|
+
def write_point(points,fn):
|
|
178
|
+
new_file = open(fn,"w")
|
|
179
|
+
count = 0
|
|
180
|
+
for i in points:
|
|
181
|
+
count += 1
|
|
182
|
+
count_str = (6-len(str(count)))*" "+str(count)
|
|
183
|
+
c = "ATOM "+count_str+" BB DUM 1 0.000 0.000 15.000 1.00 0.00"
|
|
184
|
+
xp = np.format_float_positional(i[0],precision=3)
|
|
185
|
+
yp = np.format_float_positional(i[1],precision=3)
|
|
186
|
+
zp = np.format_float_positional(i[2],precision=3)
|
|
187
|
+
xp += "0"*(3-len((xp.split(".")[1])))
|
|
188
|
+
yp += "0"*(3-len((yp.split(".")[1])))
|
|
189
|
+
zp += "0"*(3-len((zp.split(".")[1])))
|
|
190
|
+
new_c = c[:30]+(" "*(8-len(xp)))+xp+(" "*(8-len(yp)))+yp+(" "*(8-len(zp))) +zp+c[54:]+"\n"
|
|
191
|
+
new_file.write(new_c)
|
|
192
|
+
new_file.close()
|
|
193
|
+
|
|
194
|
+
def write_protein(bfacs,fn,ofn):
|
|
195
|
+
new_file = open(fn,"r")
|
|
196
|
+
n_lines = new_file.readlines()
|
|
197
|
+
new_file.close()
|
|
198
|
+
out_file = open(ofn,"w")
|
|
199
|
+
bc = 0
|
|
200
|
+
for c in n_lines:
|
|
201
|
+
if len(c) > 54 and "[" not in c and c.startswith("ATOM"):
|
|
202
|
+
bbp = np.format_float_positional(bfacs[map_to_beads[bc]],precision=3)
|
|
203
|
+
bbp += "0"*(3-len((bbp.split(".")[1])))
|
|
204
|
+
new_c = c[:60]+(" "*(8-len(bbp)))+bbp+c[68:]
|
|
205
|
+
bc+=1
|
|
206
|
+
out_file.write(new_c)
|
|
207
|
+
else:
|
|
208
|
+
out_file.write(c)
|
|
209
|
+
out_file.close()
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
#lennard jones function with values <r cutoff
|
|
213
|
+
@jax.jit
|
|
214
|
+
def lj(r,min_pos):
|
|
215
|
+
ret_val = 0
|
|
216
|
+
def lmp(r):
|
|
217
|
+
return min_pos*twopowsixth
|
|
218
|
+
def nlmp(r):
|
|
219
|
+
return r
|
|
220
|
+
r = jax.lax.cond(r<min_pos*twopowsixth,lmp,nlmp,r)
|
|
221
|
+
ret_val = 4*(jnp.power((min_pos/r),12)-jnp.power((min_pos/r),6))
|
|
222
|
+
return ret_val
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def get_loop_inds(n,nx,ny):
|
|
226
|
+
indsx = np.arange(nx-2*n+2)+(n-1)
|
|
227
|
+
indsy = np.arange(ny-2*n+2)+(n-1)
|
|
228
|
+
y0 = np.zeros(nx-2*n+2)+indsy[0]
|
|
229
|
+
yn = np.zeros(nx-2*n+2)+indsy[-1]
|
|
230
|
+
p0 = np.zeros(nx-2*n+2)-1
|
|
231
|
+
pp0 = np.zeros(nx-2*n+2)
|
|
232
|
+
pp0[0] += 1
|
|
233
|
+
pp0[-1] -= 1
|
|
234
|
+
pn = np.zeros(nx-2*n+2)+1
|
|
235
|
+
line1 = np.concatenate((indsx[:,None],y0[:,None],pp0[:,None],pn[:,None]),axis=1)
|
|
236
|
+
line2 = np.concatenate((indsx[:,None],yn[:,None],pp0[:,None],p0[:,None]),axis=1)
|
|
237
|
+
x0 = np.zeros(ny-2*n)+indsx[0]
|
|
238
|
+
xn = np.zeros(ny-2*n)+indsx[-1]
|
|
239
|
+
p0 = np.zeros(ny-2*n)-1
|
|
240
|
+
pp0 = np.zeros(ny-2*n)
|
|
241
|
+
pn = np.zeros(ny-2*n)+1
|
|
242
|
+
line3 = np.concatenate((x0[:,None],indsy[1:-1,None],pn[:,None],pp0[:,None]),axis=1)
|
|
243
|
+
line4 = np.concatenate((xn[:,None],indsy[1:-1,None],p0[:,None],pp0[:,None]),axis=1)
|
|
244
|
+
return np.concatenate((line1,line2,line3,line4))
|
|
245
|
+
|
|
246
|
+
def get_all_loop_inds(k,nx,ny):
|
|
247
|
+
all_inds = np.empty((0,4))
|
|
248
|
+
for i in range(k):
|
|
249
|
+
all_inds = np.concatenate((get_loop_inds(i+1,nx,ny),all_inds))
|
|
250
|
+
return all_inds
|
|
251
|
+
|
|
252
|
+
def get_new_zs(new_zs,loop_inds):
|
|
253
|
+
nx = new_zs.shape[0]
|
|
254
|
+
ny = new_zs.shape[1]
|
|
255
|
+
def loop1(new_zs,ind):
|
|
256
|
+
inder = jnp.array(loop_inds[ind],dtype=int)
|
|
257
|
+
ix = inder[0]
|
|
258
|
+
iy = inder[1]
|
|
259
|
+
inderm1 = inder.at[:2].set(inder[:2]+inder[2:])
|
|
260
|
+
ixl = inderm1[0]
|
|
261
|
+
iyl = inderm1[1]
|
|
262
|
+
new_zs = new_zs.at[ix,iy,0].set(new_zs[ix,iy,0]+new_zs[ixl,iyl,0])
|
|
263
|
+
return new_zs , ind
|
|
264
|
+
new_zs,_ = jax.lax.scan(loop1,new_zs,jnp.arange(loop_inds.shape[0]))
|
|
265
|
+
return new_zs
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
#Sigmoid function
|
|
273
|
+
@jax.jit
|
|
274
|
+
def sj(x,grad):
|
|
275
|
+
ret_val = -x*grad
|
|
276
|
+
def overflow_pos(ret_val):
|
|
277
|
+
ret_val = 100.0
|
|
278
|
+
return ret_val
|
|
279
|
+
def overflow_neg(ret_val):
|
|
280
|
+
ret_val = -100.0
|
|
281
|
+
return ret_val
|
|
282
|
+
def not_overflow(ret_val):
|
|
283
|
+
return ret_val
|
|
284
|
+
|
|
285
|
+
ret_val = jax.lax.cond(-x*grad>100,overflow_pos,not_overflow,ret_val)
|
|
286
|
+
ret_val = jax.lax.cond(-x*grad<-100,overflow_neg,not_overflow,ret_val)
|
|
287
|
+
return 1.0/(1.0+jnp.exp(ret_val))
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
#Two variations of the mean field function
|
|
291
|
+
@jax.jit
|
|
292
|
+
def smj(x,grad,bead_num,mem_structure):
|
|
293
|
+
l1min = (W_B_mins[bead_num]+LH1_B_mins[bead_num]-jnp.abs(W_B_mins[bead_num]-LH1_B_mins[bead_num]))/2
|
|
294
|
+
l2min = (W_B_mins[bead_num]+LH2_B_mins[bead_num]-jnp.abs(W_B_mins[bead_num]-LH2_B_mins[bead_num]))/2
|
|
295
|
+
l3min = (W_B_mins[bead_num]+LH3_B_mins[bead_num]-jnp.abs(W_B_mins[bead_num]-LH3_B_mins[bead_num]))/2
|
|
296
|
+
bd1 = (1.0-sj(x-mem_structure[0],grad))*W_B_mins[bead_num]+sj(x-mem_structure[0],grad)*l1min
|
|
297
|
+
bd2 = (1.0-sj(x-mem_structure[1],grad))*bd1+sj(x-mem_structure[1],grad)*l2min
|
|
298
|
+
bd3 = (1.0-sj(x-mem_structure[2],grad))*bd2+sj(x-mem_structure[2],grad)*l3min
|
|
299
|
+
bd4 = (1.0-sj(x-mem_structure[3],grad))*bd3+sj(x-mem_structure[3],grad)*LT1_B_mins[bead_num]
|
|
300
|
+
bd5 = (1.0-sj(x-mem_structure[4],grad))*bd4+sj(x-mem_structure[4],grad)*l3min
|
|
301
|
+
bd6 = (1.0-sj(x-mem_structure[5],grad))*bd5+sj(x-mem_structure[5],grad)*l2min
|
|
302
|
+
bd7 = (1.0-sj(x-mem_structure[6],grad))*bd6+sj(x-mem_structure[6],grad)*l1min
|
|
303
|
+
bd8 = (1.0-sj(x-mem_structure[7],grad))*bd7+sj(x-mem_structure[7],grad)*W_B_mins[bead_num]
|
|
304
|
+
return bd8-W_B_mins[bead_num]
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
@jax.jit
|
|
308
|
+
def smjh(x,grad,bead_num,mem_structure):
|
|
309
|
+
bd1 = (1.0-sj(x-mem_structure[0],grad))*W_B_mins[bead_num]+sj(x-mem_structure[0],grad)*LH1_B_mins[bead_num]
|
|
310
|
+
bd2 = (1.0-sj(x-mem_structure[1],grad))*bd1+sj(x-mem_structure[1],grad)*LH2_B_mins[bead_num]
|
|
311
|
+
bd3 = (1.0-sj(x-mem_structure[2],grad))*bd2+sj(x-mem_structure[2],grad)*LH3_B_mins[bead_num]
|
|
312
|
+
bd4 = (1.0-sj(x-mem_structure[3],grad))*bd3+sj(x-mem_structure[3],grad)*LT1_B_mins[bead_num]
|
|
313
|
+
bd5 = (1.0-sj(x-mem_structure[4],grad))*bd4+sj(x-mem_structure[4],grad)*LH3_B_mins[bead_num]
|
|
314
|
+
bd6 = (1.0-sj(x-mem_structure[5],grad))*bd5+sj(x-mem_structure[5],grad)*LH2_B_mins[bead_num]
|
|
315
|
+
bd7 = (1.0-sj(x-mem_structure[6],grad))*bd6+sj(x-mem_structure[6],grad)*LH1_B_mins[bead_num]
|
|
316
|
+
bd8 = (1.0-sj(x-mem_structure[7],grad))*bd7+sj(x-mem_structure[7],grad)*W_B_mins[bead_num]
|
|
317
|
+
return bd8-W_B_mins[bead_num]
|
|
318
|
+
|
|
319
|
+
#Creates a list containing the membrane structure for a given membrane thickness
|
|
320
|
+
def get_mem_struc(mt):
|
|
321
|
+
memt_tails = mt
|
|
322
|
+
memt_heads = 10.0
|
|
323
|
+
memt_total = memt_tails+memt_heads
|
|
324
|
+
|
|
325
|
+
h1_w = memt_heads/6.0
|
|
326
|
+
h2_w = memt_heads/6.0
|
|
327
|
+
h3_w = memt_heads/6.0
|
|
328
|
+
|
|
329
|
+
l_w = memt_tails
|
|
330
|
+
meml = -l_w/2.0 -h1_w -h2_w-h3_w
|
|
331
|
+
mem_structure = jnp.array([meml,meml+h1_w,meml+h2_w+h1_w,meml+h2_w+h1_w+h3_w,meml+h2_w+h1_w+h3_w+l_w,meml+h2_w+h1_w+2*h3_w+l_w,meml+2*h2_w+h1_w+2*h3_w+l_w,meml+2*h2_w+2*h1_w+2*h3_w+l_w])
|
|
332
|
+
return mem_structure
|
|
333
|
+
|
|
334
|
+
#A fucntion that reads a martini file to get interaction strengths
|
|
335
|
+
def get_int_strength(bead_1,bead_2,martini_file):
|
|
336
|
+
if(bead_2 == "GHOST"):
|
|
337
|
+
return 0
|
|
338
|
+
string = " "*(6-len(bead_1))+bead_1+" "*(6-len(bead_2))+bead_2
|
|
339
|
+
string2 = " "*(6-len(bead_2))+bead_2+" "*(6-len(bead_1))+bead_1
|
|
340
|
+
mfile = open(martini_file,"r")
|
|
341
|
+
content = mfile.readlines()
|
|
342
|
+
for i,line in enumerate(content):
|
|
343
|
+
if(string in line or string2 in line):
|
|
344
|
+
return -float(line[32:45])
|
|
345
|
+
|
|
346
|
+
#Gets the interations between protein beads and the enviroment. This is used to create the mean fields
|
|
347
|
+
def get_mem_def(martini_file):
|
|
348
|
+
Beadtype_names = list(Beadtype.keys())
|
|
349
|
+
no_beadtypes = len(Beadtype_names)
|
|
350
|
+
#We use interactions strengths from martini using a POPE(Q4p)/POPG(P4)/POPC(Q1)? lipid as a template
|
|
351
|
+
W_B_mins = jnp.array([get_int_strength("W",Beadtype_names[i],martini_file)-get_int_strength("W",Beadtype_names[i],martini_file) for i in range(no_beadtypes)])
|
|
352
|
+
LH1_B_mins = jnp.array([get_int_strength("P4",Beadtype_names[i],martini_file)-get_int_strength("W",Beadtype_names[i],martini_file) for i in range(no_beadtypes)])
|
|
353
|
+
LH2_B_mins = jnp.array([get_int_strength("Q5",Beadtype_names[i],martini_file)-get_int_strength("W",Beadtype_names[i],martini_file) for i in range(no_beadtypes)])
|
|
354
|
+
LH3_B_mins = jnp.array([get_int_strength("SN4a",Beadtype_names[i],martini_file)-get_int_strength("W",Beadtype_names[i],martini_file) for i in range(no_beadtypes)])
|
|
355
|
+
LH4_B_mins = jnp.array([get_int_strength("N4a",Beadtype_names[i],martini_file)-get_int_strength("W",Beadtype_names[i],martini_file) for i in range(no_beadtypes)])
|
|
356
|
+
LT1_B_mins = jnp.array([get_int_strength("C1",Beadtype_names[i],martini_file)-get_int_strength("W",Beadtype_names[i],martini_file) for i in range(no_beadtypes)])
|
|
357
|
+
LT2_B_mins = jnp.array([get_int_strength("C4h",Beadtype_names[i],martini_file)-get_int_strength("W",Beadtype_names[i],martini_file) for i in range(no_beadtypes)])
|
|
358
|
+
Charge_B_mins =jnp.array([0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,-1,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],dtype="float64")
|
|
359
|
+
# 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 # #
|
|
360
|
+
return (W_B_mins,LH1_B_mins,LH2_B_mins,LH3_B_mins,LH4_B_mins,LT1_B_mins,LT2_B_mins,Charge_B_mins)
|
|
361
|
+
|
|
362
|
+
#Gets the n closest neighbours in a grid
|
|
363
|
+
def get_nbh_inds(inder,nx,ny,n):
|
|
364
|
+
ix,iy = unflat_ind(inder,nx)
|
|
365
|
+
|
|
366
|
+
defs = jnp.arange(2*n+1)-n
|
|
367
|
+
nbh_inds = jnp.zeros(defs.shape[0]*defs.shape[0])
|
|
368
|
+
def l1(nbh_inds,ind):
|
|
369
|
+
ind1 = ind
|
|
370
|
+
def l2(nbh_inds,ind):
|
|
371
|
+
new_x = ix+defs[ind1]
|
|
372
|
+
new_y = iy+defs[ind]
|
|
373
|
+
def wrap_up(new_ind,ind_x):
|
|
374
|
+
return new_ind+ind_x
|
|
375
|
+
def wrap_down(new_ind,ind_x):
|
|
376
|
+
return new_ind-ind_x
|
|
377
|
+
def nothing(new_ind,ind_x):
|
|
378
|
+
return new_ind
|
|
379
|
+
|
|
380
|
+
new_x = jax.lax.cond(new_x>=nx,wrap_down,nothing,new_x,nx)
|
|
381
|
+
new_y = jax.lax.cond(new_y>=ny,wrap_down,nothing,new_y,ny)
|
|
382
|
+
new_x = jax.lax.cond(new_x<0,wrap_up,nothing,new_x,nx)
|
|
383
|
+
new_y = jax.lax.cond(new_y<0,wrap_up,nothing,new_y,ny)
|
|
384
|
+
|
|
385
|
+
nbh_inds = nbh_inds.at[ind1*defs.shape[0]+ind].set(flat_ind(new_x,new_y,nx))
|
|
386
|
+
return nbh_inds,ind
|
|
387
|
+
nbh_inds,_=jax.lax.scan(l2,nbh_inds,jnp.arange(defs.shape[0]))
|
|
388
|
+
return nbh_inds,ind
|
|
389
|
+
nbh_inds,_=jax.lax.scan(l1,nbh_inds,jnp.arange(defs.shape[0]))
|
|
390
|
+
return nbh_inds
|
|
391
|
+
|
|
392
|
+
#Writes the deformations pdb file
|
|
393
|
+
def write_pdb(start_z,grid_in,grid_ban,nx,ny,exx,exy,gc,defo_dir,locdir,memdir,bfacs,memdata,rot_mat_inv):
|
|
394
|
+
BanGrid = np.zeros((nx,ny,2))
|
|
395
|
+
Data = np.zeros((nx,ny,2))
|
|
396
|
+
new_file = open(defo_dir+"Deformations.pdb","w")
|
|
397
|
+
grid_in = np.array(grid_in)
|
|
398
|
+
count = 0
|
|
399
|
+
xs = np.linspace(-exx,exx,nx)
|
|
400
|
+
ys = np.linspace(-exy,exy,ny)
|
|
401
|
+
np.savez(locdir+"Xlin.npz",xs)
|
|
402
|
+
np.savez(locdir+"Ylin.npz",ys)
|
|
403
|
+
np.savez(memdir+"Xlin.npz",xs)
|
|
404
|
+
np.savez(memdir+"Ylin.npz",ys)
|
|
405
|
+
for i in range(nx):
|
|
406
|
+
for j in range(ny):
|
|
407
|
+
if(grid_ban[i,j] == 1):
|
|
408
|
+
ms = get_mem_struc(grid_in[i,j,1])
|
|
409
|
+
ms_av = get_mem_struc(grid_in[0,0,1])
|
|
410
|
+
z_pluss = [ms[0],ms[7]]
|
|
411
|
+
z_pluss_av = [ms_av[0],ms_av[7]]
|
|
412
|
+
for nn,zz in enumerate(z_pluss):
|
|
413
|
+
pm1 = (nn-0.5)*2
|
|
414
|
+
zp = zz+start_z/5
|
|
415
|
+
z_dev = np.mean(grid_in[0,:,0]+z_pluss_av[nn]+start_z/5)
|
|
416
|
+
zp_vpos = jnp.array(((grid_in[i,j,0]+zp+vext)/(2*vext))*vert_grid_size,dtype=int)
|
|
417
|
+
zp_vposc = jnp.array(((grid_in[i,j,0]+vext)/(2*vext))*vert_grid_size,dtype=int)
|
|
418
|
+
if(zp_vpos < zp_vposc):
|
|
419
|
+
lb = zp_vpos
|
|
420
|
+
rb = zp_vposc
|
|
421
|
+
else:
|
|
422
|
+
lb = zp_vposc
|
|
423
|
+
rb = zp_vpos
|
|
424
|
+
lenny = rb-lb
|
|
425
|
+
if(lb > 49):
|
|
426
|
+
lb = 49
|
|
427
|
+
if(rb > 49):
|
|
428
|
+
rb=49
|
|
429
|
+
if(lb<0):
|
|
430
|
+
lb=0
|
|
431
|
+
if(rb<0):
|
|
432
|
+
rb=0
|
|
433
|
+
covp = jnp.sum(bgrid_o[i,j,lb:rb])/lenny
|
|
434
|
+
if(covp > 0.6):
|
|
435
|
+
BanGrid[i,j,nn] = 1
|
|
436
|
+
Data[i,j,nn] = grid_in[i,j,0]+zp
|
|
437
|
+
if(bfacs):
|
|
438
|
+
bbp = np.format_float_positional(gc[i,j,nn],precision=3)
|
|
439
|
+
else:
|
|
440
|
+
bbp = np.format_float_positional((grid_in[i,j,0]+zp-z_dev)*pm1,precision=3)
|
|
441
|
+
bbp += "0"*(3-len((bbp.split(".")[1])))
|
|
442
|
+
count += 1
|
|
443
|
+
count_str = (6-len(str(count)))*" "+str(count)
|
|
444
|
+
c = "ATOM "+count_str+" BB DUM Z 1 0.000 0.000 15.000 1.00 0.00"
|
|
445
|
+
|
|
446
|
+
pos = np.array([xs[i],ys[j],0])
|
|
447
|
+
pos = np.dot(rot_mat_inv,pos)
|
|
448
|
+
xp = np.format_float_positional(pos[0],precision=3)
|
|
449
|
+
yp = np.format_float_positional(pos[1],precision=3)
|
|
450
|
+
zp = np.format_float_positional(grid_in[i,j,0]+zp,precision=3)
|
|
451
|
+
xp += "0"*(3-len((xp.split(".")[1])))
|
|
452
|
+
yp += "0"*(3-len((yp.split(".")[1])))
|
|
453
|
+
zp += "0"*(3-len((zp.split(".")[1])))
|
|
454
|
+
new_c = c[:30]+(" "*(8-len(xp)))+xp+(" "*(8-len(yp)))+yp+(" "*(8-len(zp))) +zp+c[54:60]+(" "*(8-len(bbp)))+bbp+c[66:]+"\n"
|
|
455
|
+
new_file.write(new_c)
|
|
456
|
+
new_file.close()
|
|
457
|
+
np.savez(locdir+"BotBan.npz",BanGrid[:,:,0])
|
|
458
|
+
np.savez(locdir+"TopBan.npz",BanGrid[:,:,1])
|
|
459
|
+
np.savez(locdir+"BotData.npz",Data[:,:,0])
|
|
460
|
+
np.savez(locdir+"TopData.npz",Data[:,:,1])
|
|
461
|
+
return BanGrid[:,:,0],BanGrid[:,:,1]
|
|
462
|
+
|
|
463
|
+
#calcualtes the eleectrostatic force using below
|
|
464
|
+
def calc_esf(start_z,grid_in,grid_ban,nx,ny,exx,exy,cposes,ctypes):
|
|
465
|
+
grid_in = np.array(grid_in)
|
|
466
|
+
grid_charge = np.zeros((nx,ny,2))
|
|
467
|
+
count = 0
|
|
468
|
+
xs = np.linspace(-exx,exx,nx)
|
|
469
|
+
ys = np.linspace(-exy,exy,ny)
|
|
470
|
+
for i in range(nx):
|
|
471
|
+
for j in range(ny):
|
|
472
|
+
if(grid_ban[i,j] == 1):
|
|
473
|
+
ms = get_mem_struc(grid_in[i,j,1])
|
|
474
|
+
z_pluss = [ms[0],ms[7]]
|
|
475
|
+
for nn,zz in enumerate(z_pluss):
|
|
476
|
+
zp = zz+start_z/5
|
|
477
|
+
x_pos = xs[i]
|
|
478
|
+
y_pos = ys[j]
|
|
479
|
+
z_pos = grid_in[i,j,0]+zp
|
|
480
|
+
grid_charge[i][j][nn] = calc_esf_p(jnp.array([x_pos,y_pos,z_pos]),cposes,ctypes)
|
|
481
|
+
return grid_charge
|
|
482
|
+
|
|
483
|
+
#calcues the electrostatic force
|
|
484
|
+
@jax.jit
|
|
485
|
+
def calc_esf_p(pos,cposes,ctypes):
|
|
486
|
+
ctypes = jnp.array(ctypes,dtype=int)
|
|
487
|
+
charge_const = 92.64
|
|
488
|
+
Charge_B_mins =jnp.array([0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,-1,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0],dtype="float64")
|
|
489
|
+
def esf_loop(carry,ind):
|
|
490
|
+
charge_cont = Charge_B_mins[ctypes[ind]]*charge_const/jnp.linalg.norm(pos-cposes[ind])
|
|
491
|
+
carry += charge_cont
|
|
492
|
+
return carry,ind
|
|
493
|
+
tot_c,_ = jax.lax.scan(esf_loop,0,jnp.arange(cposes.shape[0]))
|
|
494
|
+
return tot_c
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
|
|
500
|
+
#Creating a helper class that deals with loading the PDB files
|
|
501
|
+
PDB_helper_test = ori.PDB_helper(fn,False,0,np.array([]),args.no_cavity_surface,True)
|
|
502
|
+
|
|
503
|
+
#Loading PDB
|
|
504
|
+
pos_mean = PDB_helper_test.load_pdb()
|
|
505
|
+
|
|
506
|
+
|
|
507
|
+
#Getting surface
|
|
508
|
+
print("Getting surface residues...")
|
|
509
|
+
timer = time.time()
|
|
510
|
+
jax.block_until_ready(PDB_helper_test.get_surface())
|
|
511
|
+
PDB_helper_test.recenter_bvals()
|
|
512
|
+
data = PDB_helper_test.get_data()
|
|
513
|
+
|
|
514
|
+
Beadtype = ori.Beadtype
|
|
515
|
+
int_data = get_mem_def(martini_file)
|
|
516
|
+
print("Done in:", str(np.format_float_positional(time.time()-timer,precision=3))+"s")
|
|
517
|
+
|
|
518
|
+
#storing important data
|
|
519
|
+
surf_poses = data[2]+pos_mean
|
|
520
|
+
poses = data[5]+pos_mean
|
|
521
|
+
surf_bvals = data[4]
|
|
522
|
+
bead_types = data[3]
|
|
523
|
+
surface_no = data[0]
|
|
524
|
+
map_to_beads = data[9]
|
|
525
|
+
|
|
526
|
+
|
|
527
|
+
#Rotates the protein to minimise the overall size of the grid. This improves efficiency for wide proteins.
|
|
528
|
+
print("Optimising grid...")
|
|
529
|
+
timer = time.time()
|
|
530
|
+
|
|
531
|
+
angs = jnp.linspace(0,jnp.pi,200)
|
|
532
|
+
def min_extent(carry,ind):
|
|
533
|
+
nang = angs[ind]
|
|
534
|
+
rot_mat = jnp.array([[jnp.cos(nang),-jnp.sin(nang),0],[jnp.sin(nang),jnp.cos(nang),0],[0,0,1]])
|
|
535
|
+
test_surf_poses = jnp.dot(rot_mat,poses.T).T
|
|
536
|
+
x_ext = jnp.maximum(-jnp.min(test_surf_poses[:,0]),jnp.max(test_surf_poses[:,0]))
|
|
537
|
+
y_ext = jnp.maximum(-jnp.min(test_surf_poses[:,1]),jnp.max(test_surf_poses[:,1]))
|
|
538
|
+
def lower(carry):
|
|
539
|
+
carry[0] = nang
|
|
540
|
+
carry[1] = x_ext*y_ext
|
|
541
|
+
return carry
|
|
542
|
+
def higher(carry):
|
|
543
|
+
return carry
|
|
544
|
+
carry = jax.lax.cond(carry[1] > x_ext*y_ext,lower,higher,carry)
|
|
545
|
+
return carry,ind
|
|
546
|
+
|
|
547
|
+
carry,_ = jax.lax.scan(min_extent,[0.0,jnp.inf],jnp.arange(200))
|
|
548
|
+
nang = carry[0]
|
|
549
|
+
rot_mat = jnp.array([[jnp.cos(nang),-jnp.sin(nang),0],[jnp.sin(nang),jnp.cos(nang),0],[0,0,1]])
|
|
550
|
+
rot_mat_inv = jnp.array([[jnp.cos(-nang),-jnp.sin(-nang),0],[jnp.sin(-nang),jnp.cos(-nang),0],[0,0,1]])
|
|
551
|
+
surf_poses = jnp.dot(rot_mat,surf_poses.T).T
|
|
552
|
+
poses = jnp.dot(rot_mat,poses.T).T
|
|
553
|
+
|
|
554
|
+
|
|
555
|
+
print("Done in:", str(np.format_float_positional(time.time()-timer,precision=3))+"s")
|
|
556
|
+
timer = time.time()
|
|
557
|
+
|
|
558
|
+
#Getting the chared residues for charge calculations later
|
|
559
|
+
print("Getting charged residues...")
|
|
560
|
+
|
|
561
|
+
surf_cposes = jnp.zeros((surf_poses.shape[0],3))
|
|
562
|
+
cbead_types = jnp.zeros(bead_types.shape[0])
|
|
563
|
+
|
|
564
|
+
def cloop(carry,ind):
|
|
565
|
+
def charged(carry):
|
|
566
|
+
new0 = carry[0].at[carry[2]].set(surf_poses[ind])
|
|
567
|
+
new1 = carry[1].at[carry[2]].set(bead_types[ind])
|
|
568
|
+
new2 = carry[2] + 1
|
|
569
|
+
return (new0,new1,new2)
|
|
570
|
+
def ncharged(carry):
|
|
571
|
+
return carry
|
|
572
|
+
carry = jax.lax.cond((bead_types[ind] == 12)+(bead_types[ind] == 13)+(bead_types[ind] == 16)+(bead_types[ind] == 17),charged,ncharged,carry)
|
|
573
|
+
return carry,ind
|
|
574
|
+
|
|
575
|
+
carry = (surf_cposes,cbead_types,0)
|
|
576
|
+
carry,_ = jax.lax.scan(cloop,carry,jnp.arange(surf_poses.shape[0]))
|
|
577
|
+
cposes = carry[0][:carry[2]]
|
|
578
|
+
ctypes = carry[1][:carry[2]]
|
|
579
|
+
|
|
580
|
+
print("Done in:", str(np.format_float_positional(time.time()-timer,precision=3))+"s")
|
|
581
|
+
|
|
582
|
+
|
|
583
|
+
#setting up variables used later
|
|
584
|
+
|
|
585
|
+
vert_grid_size = 50
|
|
586
|
+
vext = 50
|
|
587
|
+
vlin = jnp.linspace(-vext,vext,vert_grid_size)
|
|
588
|
+
|
|
589
|
+
indexer = np.nonzero((np.array(surf_poses[:,2]) < 50)*(np.array(surf_poses[:,2] > -50)))
|
|
590
|
+
|
|
591
|
+
surf_poses = surf_poses[indexer]
|
|
592
|
+
surf_bvals = surf_bvals[indexer]
|
|
593
|
+
bead_types = bead_types[indexer]
|
|
594
|
+
|
|
595
|
+
indexer2 = np.nonzero((np.array(poses[:,2]) < 50)*(np.array(poses[:,2] > -50)))
|
|
596
|
+
|
|
597
|
+
all_poses = poses.copy()
|
|
598
|
+
poses = poses[indexer2]
|
|
599
|
+
|
|
600
|
+
cutoff = int(args.cutoff)
|
|
601
|
+
|
|
602
|
+
x_ext = max(-jnp.min(surf_poses[:,0]),jnp.max(surf_poses[:,0]))+25
|
|
603
|
+
y_ext = max(-jnp.min(surf_poses[:,1]),jnp.max(surf_poses[:,1]))+25
|
|
604
|
+
grid_den = float(args.grid_density)
|
|
605
|
+
|
|
606
|
+
rad = int(4.0/grid_den)
|
|
607
|
+
|
|
608
|
+
grid_size_x = int(2*x_ext/grid_den)
|
|
609
|
+
grid_size_y = int(2*y_ext/grid_den)
|
|
610
|
+
|
|
611
|
+
loop_inds = jnp.array(get_all_loop_inds(12,grid_size_x,grid_size_y))
|
|
612
|
+
loop_inds_end = np.array(get_loop_inds(1,grid_size_x,grid_size_y),dtype=int)
|
|
613
|
+
|
|
614
|
+
nxx = jnp.array(x_ext/cutoff,dtype=int)
|
|
615
|
+
nyy = jnp.array(y_ext/cutoff,dtype=int)
|
|
616
|
+
|
|
617
|
+
no_beads = surf_poses.shape[0]
|
|
618
|
+
|
|
619
|
+
#Putting beads into bins for more efficient allocation of beads to membrane segments later on
|
|
620
|
+
print("Binning surface... (This could take a short while)")
|
|
621
|
+
timer = time.time()
|
|
622
|
+
@jax.jit
|
|
623
|
+
def allo_bead(surf_poses):
|
|
624
|
+
no_beads = surf_poses.shape[0]
|
|
625
|
+
big_grid = jnp.zeros((grid_size_x,grid_size_y,no_beads+1),dtype=int)-1
|
|
626
|
+
big_grid = big_grid.at[:,:,no_beads].set(0)
|
|
627
|
+
def allocacte_beads(big_grid,ind):
|
|
628
|
+
bind = ind
|
|
629
|
+
x_pos = surf_poses[bind][0]
|
|
630
|
+
y_pos = surf_poses[bind][1]
|
|
631
|
+
xgrid,ygrid = put_into_grid([x_pos,y_pos],[2*x_ext,2*y_ext],[nxx,nyy],[-x_ext,-y_ext])
|
|
632
|
+
big_grid = big_grid.at[xgrid,ygrid,big_grid[xgrid,ygrid,-1]].set(bind)
|
|
633
|
+
big_grid = big_grid.at[xgrid,ygrid,-1].set(big_grid[xgrid,ygrid,-1]+1)
|
|
634
|
+
return big_grid,ind
|
|
635
|
+
big_grid,_ = jax.lax.scan(allocacte_beads,big_grid,jnp.arange(no_beads))
|
|
636
|
+
return big_grid
|
|
637
|
+
|
|
638
|
+
big_grid = allo_bead(surf_poses)
|
|
639
|
+
big_gridb = allo_bead(poses)
|
|
640
|
+
|
|
641
|
+
max_beads = jnp.max(big_grid[:,:,-1])
|
|
642
|
+
|
|
643
|
+
print("Done in:", str(np.format_float_positional(time.time()-timer,precision=3))+"s")
|
|
644
|
+
timer = time.time()
|
|
645
|
+
|
|
646
|
+
#Allocating beads to membrane segments for use when calculating the potential. This takes some time and so is pre-calculated.
|
|
647
|
+
print("Allocating beads to membrane segments... (This could take a short while)")
|
|
648
|
+
|
|
649
|
+
xs = jnp.linspace(-x_ext,x_ext,grid_size_x)
|
|
650
|
+
ys = jnp.linspace(-y_ext,y_ext,grid_size_y)
|
|
651
|
+
indxes = jnp.zeros((grid_size_x,grid_size_y,2),dtype=int)
|
|
652
|
+
def indloop1(indxes,ind):
|
|
653
|
+
def indloop2(indxes,ind2):
|
|
654
|
+
indxes = indxes.at[ind,ind2].set(jnp.array([ind,ind2]))
|
|
655
|
+
return indxes,ind2
|
|
656
|
+
indxes,_ = jax.lax.scan(indloop2,indxes,jnp.arange(grid_size_y))
|
|
657
|
+
return indxes,ind
|
|
658
|
+
indxes,_=jax.lax.scan(indloop1,indxes,jnp.arange(grid_size_x))
|
|
659
|
+
|
|
660
|
+
indxes = indxes.reshape((grid_size_x*grid_size_y,2))
|
|
661
|
+
|
|
662
|
+
def allo_grid_vmap(cutoff_val,big_grid,surf_poses):
|
|
663
|
+
max_beads = jnp.max(big_grid[:,:,-1])
|
|
664
|
+
@partial(jax.vmap,in_axes=0)
|
|
665
|
+
def agrid_vmap(inds):
|
|
666
|
+
grid_p = jnp.zeros((no_beads+1,2),dtype=float)-1
|
|
667
|
+
grid_p = grid_p.at[no_beads,:].set(0)
|
|
668
|
+
ind2 = inds[0]
|
|
669
|
+
ind3 = inds[1]
|
|
670
|
+
indx,indy = put_into_grid([xs[ind2],ys[ind3]],[2*x_ext,2*y_ext],[nxx,nyy],[-x_ext,-y_ext])
|
|
671
|
+
sq = jnp.array([[0,0],[-1,0],[1,0],[0,-1],[0,1],[-1,1],[-1,-1],[1,1],[1,-1]],dtype=int)
|
|
672
|
+
def allocate_grid3(grid_p,ind):
|
|
673
|
+
def allocate_grid4(grid_p,sind):
|
|
674
|
+
bgind = big_grid[(indx+sq[sind,0])%grid_size_x,(indy+sq[sind,1])%grid_size_y][ind]
|
|
675
|
+
def close(grid_p,dist):
|
|
676
|
+
indeex = jnp.array(grid_p[-1,0],dtype=int)
|
|
677
|
+
grid_p = grid_p.at[indeex,0].set(bgind)
|
|
678
|
+
grid_p = grid_p.at[indeex,1].set(dist)
|
|
679
|
+
grid_p = grid_p.at[-1,0].set(grid_p[-1,0]+1)
|
|
680
|
+
return grid_p
|
|
681
|
+
def far(grid_p,dist):
|
|
682
|
+
return grid_p
|
|
683
|
+
def is_bead(grid_p):
|
|
684
|
+
pos = surf_poses[bgind][0:2]
|
|
685
|
+
grid_pos = jnp.array([xs[ind2],ys[ind3]])
|
|
686
|
+
dist = jnp.linalg.norm(pos-grid_pos)
|
|
687
|
+
grid_p = jax.lax.cond(dist < cutoff_val, close,far,grid_p,dist)
|
|
688
|
+
return grid_p
|
|
689
|
+
def isn_bead(grid_p):
|
|
690
|
+
return grid_p
|
|
691
|
+
grid_p= jax.lax.cond(bgind != -1,is_bead,isn_bead,grid_p)
|
|
692
|
+
return grid_p,sind
|
|
693
|
+
grid_p,_ = jax.lax.scan(allocate_grid4,grid_p,jnp.arange(9))
|
|
694
|
+
return grid_p,ind
|
|
695
|
+
grid_p,_ = jax.lax.scan(allocate_grid3,grid_p,jnp.arange(max_beads))
|
|
696
|
+
return grid_p
|
|
697
|
+
grid_p = agrid_vmap(indxes)
|
|
698
|
+
grid = grid_p.reshape((grid_size_x,grid_size_y,no_beads+1,2))
|
|
699
|
+
return grid
|
|
700
|
+
|
|
701
|
+
grid = allo_grid_vmap(cutoff,big_grid,surf_poses).block_until_ready()
|
|
702
|
+
grid_block = allo_grid_vmap(3.0,big_gridb,poses)
|
|
703
|
+
|
|
704
|
+
print("Done in:", str(np.format_float_positional(time.time()-timer,precision=3))+"s")
|
|
705
|
+
timer = time.time()
|
|
706
|
+
|
|
707
|
+
#Creating a smooth function that indicates if a point is with the protein or not.
|
|
708
|
+
print("Blocking membrane inside protein...")
|
|
709
|
+
|
|
710
|
+
max_beads_block = jnp.array(jnp.max(grid_block[:,:,-1,0]),dtype=int)
|
|
711
|
+
bgrid = jnp.zeros((grid_size_x,grid_size_y,vert_grid_size))+1
|
|
712
|
+
|
|
713
|
+
def gblock1(bgrid,ind):
|
|
714
|
+
ind2 = ind
|
|
715
|
+
def gblock2(bgrid,ind):
|
|
716
|
+
ind3 = ind
|
|
717
|
+
def bloop(bgrid,ind):
|
|
718
|
+
bind = jnp.array(grid_block[ind2,ind3,ind,0],dtype=int)
|
|
719
|
+
def mins(bgrid):
|
|
720
|
+
return bgrid
|
|
721
|
+
def nmins(bgrid):
|
|
722
|
+
atom_pos = poses[bind,2]
|
|
723
|
+
indap = jnp.array(((atom_pos+vext)/(2*vext))*vert_grid_size,dtype=int)
|
|
724
|
+
bgrid = bgrid.at[ind2,ind3,indap].set(0)
|
|
725
|
+
bgrid = bgrid.at[ind2,ind3,indap-1].set(0)
|
|
726
|
+
bgrid = bgrid.at[ind2,ind3,indap+1].set(0)
|
|
727
|
+
return bgrid
|
|
728
|
+
bgrid = jax.lax.cond(bind != -1,nmins,mins,bgrid)
|
|
729
|
+
return bgrid,ind
|
|
730
|
+
bgrid,_ = jax.lax.scan(bloop,bgrid,jnp.arange(max_beads_block))
|
|
731
|
+
return bgrid,ind
|
|
732
|
+
bgrid,_ = jax.lax.scan(gblock2,bgrid,jnp.arange(grid_size_y))
|
|
733
|
+
return bgrid,ind
|
|
734
|
+
bgrid,_ = jax.lax.scan(gblock1,bgrid,jnp.arange(grid_size_x))
|
|
735
|
+
|
|
736
|
+
|
|
737
|
+
mem_structure = get_mem_struc(mem_data[1])
|
|
738
|
+
|
|
739
|
+
def accessable(grid):
|
|
740
|
+
ngrid = jnp.zeros_like(grid)
|
|
741
|
+
def aloop1(ngrid,ind1):
|
|
742
|
+
def aloop2(ngrid,ind2):
|
|
743
|
+
t1 = jnp.sum(jnp.array([grid[ind1,ind2],grid[ind1-1,ind2],grid[ind1-1,ind2-1],grid[ind1,ind2-1]]))
|
|
744
|
+
t2 = jnp.sum(jnp.array([grid[ind1,ind2],grid[ind1+1,ind2],grid[ind1+1,ind2-1],grid[ind1,ind2-1]]))
|
|
745
|
+
t3 = jnp.sum(jnp.array([grid[ind1,ind2],grid[ind1-1,ind2],grid[ind1-1,ind2+1],grid[ind1,ind2+1]]))
|
|
746
|
+
t4 = jnp.sum(jnp.array([grid[ind1,ind2],grid[ind1+1,ind2],grid[ind1+1,ind2+1],grid[ind1,ind2+1]]))
|
|
747
|
+
def good(ngrid):
|
|
748
|
+
ngrid = ngrid.at[ind1,ind2].set(1)
|
|
749
|
+
return ngrid
|
|
750
|
+
def bad(ngrid):
|
|
751
|
+
return ngrid
|
|
752
|
+
ngrid = jax.lax.cond(jnp.logical_or(jnp.logical_or(t1==4,t2==4),jnp.logical_or(t3==4,t4==4)),good,bad,ngrid)
|
|
753
|
+
return ngrid,ind2
|
|
754
|
+
ngrid,_= jax.lax.scan(aloop2,ngrid,jnp.arange(ngrid.shape[1]))
|
|
755
|
+
return ngrid,ind1
|
|
756
|
+
ngrid,_ = jax.lax.scan(aloop1,ngrid,jnp.arange(ngrid.shape[0]))
|
|
757
|
+
return ngrid
|
|
758
|
+
|
|
759
|
+
grid_ban = jnp.zeros((grid_size_x,grid_size_y),dtype=int)+1
|
|
760
|
+
@jax.jit
|
|
761
|
+
def fill_mid(grid_ban,tol):
|
|
762
|
+
rdic_carry = jnp.zeros((grid_size_x*grid_size_y,3))
|
|
763
|
+
numer = grid_size_x*grid_size_y
|
|
764
|
+
rdic_carry = rdic_carry.at[0,0].set(1)
|
|
765
|
+
def remove_disc(rdic_carry,ind):
|
|
766
|
+
def check(rdic_carry):
|
|
767
|
+
rdic_carry = rdic_carry.at[ind,2].set(1)
|
|
768
|
+
def is_block(rdic_carry):
|
|
769
|
+
return rdic_carry
|
|
770
|
+
def is_no_block(rdic_carry):
|
|
771
|
+
nb_inds = jnp.array(get_nbh_inds(ind,grid_size_x,grid_size_y,1),dtype=int)
|
|
772
|
+
rdic_carry = rdic_carry.at[nb_inds,0].set(rdic_carry[nb_inds,0]+1)
|
|
773
|
+
rdic_carry = rdic_carry.at[ind,1].set(1)
|
|
774
|
+
return rdic_carry
|
|
775
|
+
rdic_carry = jax.lax.cond(grid_ban[unflat_ind(ind,grid_size_x)]>tol,is_block,is_no_block,rdic_carry)
|
|
776
|
+
return rdic_carry
|
|
777
|
+
def no_check(rdic_carry):
|
|
778
|
+
return rdic_carry
|
|
779
|
+
rdic_carry = jax.lax.cond((rdic_carry[ind,0]>0)*(rdic_carry[ind,2]==0),check,no_check,rdic_carry)
|
|
780
|
+
return rdic_carry,ind
|
|
781
|
+
|
|
782
|
+
rdic_carry,_ = jax.lax.scan(remove_disc,rdic_carry,jnp.arange(numer))
|
|
783
|
+
rdic_carry,_ = jax.lax.scan(remove_disc,rdic_carry,-jnp.arange(numer)+(numer-1))
|
|
784
|
+
transp_arange = jnp.arange(numer).reshape(grid_size_x,grid_size_y)
|
|
785
|
+
transp_arange = transp_arange.T
|
|
786
|
+
transp_arange = transp_arange.reshape(numer)
|
|
787
|
+
rdic_carry,_ = jax.lax.scan(remove_disc,rdic_carry,transp_arange)
|
|
788
|
+
rdic_carry,_ = jax.lax.scan(remove_disc,rdic_carry,-transp_arange+(numer-1))
|
|
789
|
+
return rdic_carry[:,2].reshape(grid_size_y,grid_size_x).T
|
|
790
|
+
|
|
791
|
+
bgrid_o = jnp.zeros_like(bgrid)
|
|
792
|
+
|
|
793
|
+
def fill_out_all(carry,ind):
|
|
794
|
+
bgrid = carry[0]
|
|
795
|
+
bgrid_o = carry[1]
|
|
796
|
+
tempb = fill_mid(1-accessable(bgrid[:,:,ind]),0.5)
|
|
797
|
+
bgrid_o = bgrid_o.at[:,:,ind].set(tempb)
|
|
798
|
+
bgrid = bgrid.at[:,:,ind].set(fill_mid(1-tempb,0.5))
|
|
799
|
+
return (bgrid,bgrid_o),ind
|
|
800
|
+
|
|
801
|
+
carryb,_ = jax.lax.scan(fill_out_all,(bgrid,bgrid_o),jnp.arange(vert_grid_size))
|
|
802
|
+
bgrid = carryb[0]
|
|
803
|
+
bgrid_o = carryb[1]
|
|
804
|
+
|
|
805
|
+
print("Done in:", str(np.format_float_positional(time.time()-timer,precision=3))+"s")
|
|
806
|
+
timer = time.time()
|
|
807
|
+
|
|
808
|
+
#This function indicates if grid point (i,j) and height z is within the protein.
|
|
809
|
+
@jax.jit
|
|
810
|
+
def bgrid_weight(i,j,z):
|
|
811
|
+
zind = ((z+vext)/(2*vext))*vert_grid_size
|
|
812
|
+
zind_l = jnp.array(jnp.floor(zind),dtype=int)-5
|
|
813
|
+
tot = 0
|
|
814
|
+
|
|
815
|
+
def above(zindy):
|
|
816
|
+
return vert_grid_size-1
|
|
817
|
+
def below(zindy):
|
|
818
|
+
return 0
|
|
819
|
+
def nab(zindy):
|
|
820
|
+
return jnp.array(zindy,dtype=int)
|
|
821
|
+
|
|
822
|
+
def bwloop(tot,ind):
|
|
823
|
+
zind_u = zind_l+ind
|
|
824
|
+
zind_u = jax.lax.cond(zind_u > vert_grid_size-1,above,nab,zind_u)
|
|
825
|
+
zind_u = jax.lax.cond(zind_u < 0,below,nab,zind_u)
|
|
826
|
+
tot += bgrid[i,j,zind_u]
|
|
827
|
+
|
|
828
|
+
return tot,ind
|
|
829
|
+
tot,_ = jax.lax.scan(bwloop,tot,jnp.arange(10))
|
|
830
|
+
|
|
831
|
+
zind_u = jax.lax.cond(zind_l+10 > vert_grid_size-1,above,nab,zind_l+10)
|
|
832
|
+
zind_u = jax.lax.cond(zind_l+10 < 0,below,nab,zind_l+10)
|
|
833
|
+
|
|
834
|
+
zind_l = jax.lax.cond(zind_l > vert_grid_size-1,above,nab,zind_l)
|
|
835
|
+
zind_l = jax.lax.cond(zind_l < 0,below,nab,zind_l)
|
|
836
|
+
|
|
837
|
+
tot += (bgrid[i,j,zind_u]-bgrid[i,j,zind_l])*(zind-zind_l-5)
|
|
838
|
+
return (1-jnp.cos(jnp.pi*(tot/10)))/2.0
|
|
839
|
+
|
|
840
|
+
max_beads = jnp.array(jnp.max(grid[:,:,-1,0]),dtype=int)
|
|
841
|
+
W_B_mins = int_data[0]
|
|
842
|
+
LH1_B_mins = int_data[1]
|
|
843
|
+
LH2_B_mins = int_data[2]
|
|
844
|
+
LH3_B_mins = int_data[3]
|
|
845
|
+
LH4_B_mins = int_data[4]
|
|
846
|
+
LT1_B_mins = int_data[5]
|
|
847
|
+
LT2_B_mins = int_data[6]
|
|
848
|
+
Charge_B_mins =int_data[7]
|
|
849
|
+
|
|
850
|
+
#Prevents gaps between protein and membrane
|
|
851
|
+
def intbgrid(ind2,ind3,zt,mt,zd):
|
|
852
|
+
mem_structure = get_mem_struc(mt)
|
|
853
|
+
z_disp = zt+zd
|
|
854
|
+
logs = jnp.linspace(mem_structure[0],mem_structure[-1],10)
|
|
855
|
+
sumer = 0
|
|
856
|
+
def z_range(sumer,ind):
|
|
857
|
+
zr = logs[ind]+z_disp
|
|
858
|
+
sumer += bgrid_weight(ind2,ind3,zr)
|
|
859
|
+
return sumer, ind
|
|
860
|
+
sumer,_ =jax.lax.scan(z_range,sumer,jnp.arange(10))
|
|
861
|
+
return (sj(-sumer+4,3))*(-sumer-200)/5.0
|
|
862
|
+
|
|
863
|
+
|
|
864
|
+
|
|
865
|
+
#Potential function. If surface bead or membrane segment is within the protein it's contribution is ignored
|
|
866
|
+
def get_pot(ind2,ind3,zt,mt,zd):
|
|
867
|
+
no_beads = grid[ind2,ind3,-1,0]
|
|
868
|
+
z_disp = zt+zd
|
|
869
|
+
def calc_grid3(tot,ind):
|
|
870
|
+
mem_structure = get_mem_struc(mt)
|
|
871
|
+
bind = jnp.array(grid[ind2,ind3,ind,0],dtype=int)
|
|
872
|
+
dist = grid[ind2,ind3,ind,1]
|
|
873
|
+
def nomin(tot):
|
|
874
|
+
z_pos = surf_poses[bind][2]-z_disp
|
|
875
|
+
xy_pos = surf_poses[bind][0:2]
|
|
876
|
+
indx,indy = put_into_grid([xy_pos[0],xy_pos[1]],[2*x_ext,2*y_ext],[nxx,nyy],[-x_ext,-y_ext])
|
|
877
|
+
bead_num = bead_types[bind]
|
|
878
|
+
disterz = jnp.sqrt(dist*dist)
|
|
879
|
+
def close(tot):
|
|
880
|
+
def upper(tot):
|
|
881
|
+
tot = tot.at[0].set(tot[0]+smj(z_pos,0.5,bead_num,mem_structure)*-1*lj(disterz,8.0)*bgrid_weight(ind2,ind3,z_pos)*bgrid_weight(indx,indy,z_pos))
|
|
882
|
+
return tot
|
|
883
|
+
def lower(tot):
|
|
884
|
+
tot = tot.at[1].set(tot[1]+smj(z_pos,0.5,bead_num,mem_structure)*-1*lj(disterz,8.0)*bgrid_weight(ind2,ind3,z_pos)*bgrid_weight(indx,indy,z_pos))
|
|
885
|
+
return tot
|
|
886
|
+
tot = jax.lax.cond(z_pos>0,upper,lower,tot)
|
|
887
|
+
return tot
|
|
888
|
+
def far(tot):
|
|
889
|
+
return tot
|
|
890
|
+
tot = jax.lax.cond((dist<float(args.cutoff))*(dist > 0),close,far,tot)
|
|
891
|
+
return tot
|
|
892
|
+
def miner(tot):
|
|
893
|
+
return tot
|
|
894
|
+
tot = jax.lax.cond(bind > -1e-1,nomin,miner,tot)
|
|
895
|
+
return tot,ind
|
|
896
|
+
def edge():
|
|
897
|
+
return (zt*zt)*1e-7+((mt-mem_data[1])*(mt-mem_data[1]))*1e-7
|
|
898
|
+
def nedge():
|
|
899
|
+
return (zt*zt)*1e-6+((mt-mem_data[1])*(mt-mem_data[1]))*1e-6
|
|
900
|
+
s_val = jax.lax.cond(jnp.logical_or(jnp.logical_or(ind3==0,ind3==grid.shape[1]-1),jnp.logical_or(ind2==0,ind2==grid.shape[0]-1)),edge,nedge)
|
|
901
|
+
tot,_ = jax.lax.scan(calc_grid3,jnp.array([s_val,s_val]),jnp.arange(max_beads))
|
|
902
|
+
tot += intbgrid(ind2,ind3,zt,mt,zd)
|
|
903
|
+
return tot,no_beads
|
|
904
|
+
|
|
905
|
+
#Calculates contacts with head groups and acyl tails
|
|
906
|
+
def calc_contacts(new_zs,poses,zdisp,xs,ys):
|
|
907
|
+
bfacsH = jnp.zeros(poses.shape[0])
|
|
908
|
+
bfacsT = jnp.zeros(poses.shape[0])
|
|
909
|
+
mindd = 3
|
|
910
|
+
def ccloop1(bfacs,ind1):
|
|
911
|
+
def ccloop2(bfacs,ind2):
|
|
912
|
+
mt = new_zs[ind1,ind2,1]
|
|
913
|
+
z = new_zs[ind1,ind2,0]
|
|
914
|
+
pos1 = jnp.array([xs[ind1],ys[ind2],z-mt/2.0-4+zdisp])
|
|
915
|
+
pos2 = jnp.array([xs[ind1],ys[ind2],z+mt/2.0+4+zdisp])
|
|
916
|
+
def ccloop3(bfacs,ind3):
|
|
917
|
+
bfacsH = bfacs[0]
|
|
918
|
+
bfacsT = bfacs[1]
|
|
919
|
+
posprot = poses[ind3]
|
|
920
|
+
dist1 = jnp.linalg.norm(posprot-pos1)/10
|
|
921
|
+
dist2 = jnp.linalg.norm(posprot-pos2)/10
|
|
922
|
+
|
|
923
|
+
bfacsH = bfacsH.at[ind3].set(bfacsH[ind3]+jnp.exp(-jnp.max(jnp.array([dist1*dist1,mindd])))*bgrid_weight(ind1,ind2,z-mt/2.0+4+zdisp)+jnp.exp(-jnp.max(jnp.array([dist2*dist2,mindd])))*bgrid_weight(ind1,ind2,z-mt/2.0-4+zdisp))
|
|
924
|
+
zscan = jnp.linspace(pos1[2],pos2[2],40)
|
|
925
|
+
def ccloop4(bfacsT,ind4):
|
|
926
|
+
pos3 = pos1.copy()
|
|
927
|
+
pos3 = pos3.at[2].set(zscan[ind4])
|
|
928
|
+
dist3 = jnp.linalg.norm(posprot-pos3)/10
|
|
929
|
+
bfacsT = bfacsT.at[ind3].set(bfacsT[ind3]+jnp.exp(-jnp.max(jnp.array([dist3*dist3,mindd])))*bgrid_weight(ind1,ind2,zscan[ind4]))
|
|
930
|
+
return bfacsT,ind4
|
|
931
|
+
bfacsT,_ = jax.lax.scan(ccloop4,bfacsT,jnp.arange(40))
|
|
932
|
+
return (bfacsH,bfacsT),ind3
|
|
933
|
+
bfacs,_ = jax.lax.scan(ccloop3,bfacs,jnp.arange(poses.shape[0]))
|
|
934
|
+
return bfacs,ind2
|
|
935
|
+
bfacs,_ = jax.lax.scan(ccloop2,bfacs,jnp.arange(new_zs.shape[1]))
|
|
936
|
+
return bfacs,ind1
|
|
937
|
+
bfacs,_ = jax.lax.scan(ccloop1,(bfacsH,bfacsT),jnp.arange(new_zs.shape[0]))
|
|
938
|
+
return bfacs
|
|
939
|
+
|
|
940
|
+
PhtoW = get_int_strength("C1","W",martini_file)-get_int_strength("C1","W",martini_file)
|
|
941
|
+
PhtoPh = get_int_strength("C1","C1",martini_file)-get_int_strength("C1","W",martini_file)
|
|
942
|
+
PhtoH = get_int_strength("P4","C1",martini_file)-get_int_strength("C1","W",martini_file)
|
|
943
|
+
HtoH = get_int_strength("P4","P4",martini_file)-get_int_strength("C1","W",martini_file)
|
|
944
|
+
HtoW = get_int_strength("P4","W",martini_file)-get_int_strength("C1","W",martini_file)
|
|
945
|
+
WtoW = get_int_strength("W","W",martini_file)-get_int_strength("C1","W",martini_file)
|
|
946
|
+
|
|
947
|
+
|
|
948
|
+
#A smooth function that describes the membrane seegment (0 water, 1 head, 2 acyl tails)
|
|
949
|
+
@jax.jit
|
|
950
|
+
def lip_sm(x,grad,lower,upper):
|
|
951
|
+
bd1 = (1.0-sj(x-lower+5,grad))*2+sj(x-lower+5,grad)*1
|
|
952
|
+
bd2 = (1.0-sj(x-lower,grad))*bd1+sj(x-lower,grad)*0
|
|
953
|
+
bd3 = (1.0-sj(x-upper,grad))*bd2+sj(x-upper,grad)*1
|
|
954
|
+
bd4 = (1.0-sj(x-upper-5,grad))*bd3+sj(x-upper-5,grad)*2
|
|
955
|
+
return bd4
|
|
956
|
+
|
|
957
|
+
int_mat = jnp.array([[PhtoPh,PhtoH,PhtoW],[PhtoH,HtoH,HtoW],[PhtoW,HtoW,WtoW]])
|
|
958
|
+
|
|
959
|
+
#This function calculates the potential between two membrane segments via 3d linear interpolations using membrane descriptions as above
|
|
960
|
+
@jax.jit
|
|
961
|
+
def rpot_col(new_zs,inda1,indb1,inda2,indb2,dist,zd,k1):
|
|
962
|
+
dist = jnp.sqrt((inda1-inda2)*(inda1-inda2)+(indb1-indb2)*(indb1-indb2))
|
|
963
|
+
def close():
|
|
964
|
+
|
|
965
|
+
|
|
966
|
+
posi1 = new_zs[inda1,indb1]
|
|
967
|
+
upper1 = zd+posi1[0]+0.5*posi1[1]
|
|
968
|
+
lower1 = zd+posi1[0]-0.5*posi1[1]
|
|
969
|
+
|
|
970
|
+
posi2 = new_zs[inda2,indb2]
|
|
971
|
+
upper2 = zd+posi2[0]+0.5*posi2[1]
|
|
972
|
+
lower2 = zd+posi2[0]-0.5*posi2[1]
|
|
973
|
+
|
|
974
|
+
lupper = jnp.min(jnp.array([upper1,upper2]))
|
|
975
|
+
ulower = jnp.max(jnp.array([lower1,lower2]))
|
|
976
|
+
|
|
977
|
+
uupper = jnp.max(jnp.array([upper1,upper2]))
|
|
978
|
+
llower = jnp.min(jnp.array([lower1,lower2]))
|
|
979
|
+
|
|
980
|
+
poverlap = posi1[0]-posi2[0]
|
|
981
|
+
up_dist = upper1-upper2
|
|
982
|
+
lo_dist = lower1-lower2
|
|
983
|
+
|
|
984
|
+
|
|
985
|
+
def small():
|
|
986
|
+
return jnp.linspace(lower1,upper1,30)
|
|
987
|
+
def nsmall():
|
|
988
|
+
return jnp.linspace(lower2,upper2,30)
|
|
989
|
+
|
|
990
|
+
test1 = jax.lax.cond(upper1-lower1<upper2-lower2,small,nsmall)
|
|
991
|
+
test1 = jnp.concatenate((test1,jnp.array([lower1-2,upper1+2])))
|
|
992
|
+
test1 = jnp.concatenate((test1,jnp.array([lower2-2,upper2+2])))
|
|
993
|
+
|
|
994
|
+
overlap = 0
|
|
995
|
+
def rloop(overlap,ind):
|
|
996
|
+
mta = lip_sm(test1[ind],4,lower1,upper1)
|
|
997
|
+
mtb = lip_sm(test1[ind],4,lower2,upper2)
|
|
998
|
+
mtbL = jnp.floor(mtb)
|
|
999
|
+
mtaI = jnp.array(mta,dtype=int)
|
|
1000
|
+
partb = mtb-mtbL
|
|
1001
|
+
mtbU = jnp.ceil(mtb)
|
|
1002
|
+
|
|
1003
|
+
mtaL = jnp.floor(mta)
|
|
1004
|
+
mtbI = jnp.array(mtb,dtype=int)
|
|
1005
|
+
parta = mta-mtaL
|
|
1006
|
+
mtaU = jnp.ceil(mta)
|
|
1007
|
+
|
|
1008
|
+
intLL = int_mat[jnp.array(mtaL,dtype=int),jnp.array(mtbL,dtype=int)]
|
|
1009
|
+
intLU = int_mat[jnp.array(mtaL,dtype=int),jnp.array(mtbU,dtype=int)]
|
|
1010
|
+
intUL = int_mat[jnp.array(mtaU,dtype=int),jnp.array(mtbL,dtype=int)]
|
|
1011
|
+
intUU = int_mat[jnp.array(mtaU,dtype=int),jnp.array(mtbU,dtype=int)]
|
|
1012
|
+
|
|
1013
|
+
intLLS = int_mat[jnp.array(mtbL,dtype=int),jnp.array(mtbL,dtype=int)]
|
|
1014
|
+
intLUS = int_mat[jnp.array(mtbL,dtype=int),jnp.array(mtbU,dtype=int)]
|
|
1015
|
+
intULS = int_mat[jnp.array(mtbU,dtype=int),jnp.array(mtbL,dtype=int)]
|
|
1016
|
+
intUUS = int_mat[jnp.array(mtbU,dtype=int),jnp.array(mtbU,dtype=int)]
|
|
1017
|
+
|
|
1018
|
+
intVL = intLL*(1-partb)+partb*intLU
|
|
1019
|
+
|
|
1020
|
+
intVU = intUL*(1-partb)+partb*intUU
|
|
1021
|
+
|
|
1022
|
+
intV = intVL*(1-parta)+parta*intVU
|
|
1023
|
+
|
|
1024
|
+
intVLS = intLLS*(1-partb)+partb*intLUS
|
|
1025
|
+
|
|
1026
|
+
intVUS = intULS*(1-partb)+partb*intUUS
|
|
1027
|
+
|
|
1028
|
+
intVS = intVLS*(1-parta)+parta*intVUS
|
|
1029
|
+
|
|
1030
|
+
overlap += intV
|
|
1031
|
+
|
|
1032
|
+
return overlap,ind
|
|
1033
|
+
overlap,_ = jax.lax.scan(rloop,overlap,jnp.arange(test1.shape[0]))
|
|
1034
|
+
|
|
1035
|
+
return overlap,poverlap,up_dist,lo_dist
|
|
1036
|
+
def nclose():
|
|
1037
|
+
return 0.0,0.0,0.0,0.0
|
|
1038
|
+
overlap,poverlap,up_dist,lo_dist = jax.lax.cond(dist<100,close,nclose)
|
|
1039
|
+
flat_d = 10
|
|
1040
|
+
usplit = sj(up_dist-flat_d,1)*jnp.power(up_dist,2)+(1-sj(up_dist+flat_d,1))*jnp.power(up_dist,2)
|
|
1041
|
+
lsplit = sj(lo_dist-flat_d,1)*jnp.power(lo_dist,2)+(1-sj(lo_dist+flat_d,1))*jnp.power(lo_dist,2)
|
|
1042
|
+
return k1*overlap*-lj(dist,1.0)+lsplit+usplit
|
|
1043
|
+
|
|
1044
|
+
#calculates the full potential due to membrane-membrane interactions
|
|
1045
|
+
@jax.jit
|
|
1046
|
+
def nbh_calc(new_zs,k,k2,zd):
|
|
1047
|
+
new_zs = get_new_zs(new_zs,loop_inds)
|
|
1048
|
+
grad_grid = jnp.zeros((grid_size_x,grid_size_y,2))
|
|
1049
|
+
def nbh_grad_calc1(grad_grid,ind2):
|
|
1050
|
+
def nbh_grad_calc2(grad_grid,ind3):
|
|
1051
|
+
inder = flat_ind(ind2,ind3,grid_size_x)
|
|
1052
|
+
all_nbhs = jnp.array(get_nbh_inds(inder,grid_size_x,grid_size_y,1),dtype=int)
|
|
1053
|
+
tot = jnp.zeros(2)
|
|
1054
|
+
posi1 = new_zs[ind2,ind3]
|
|
1055
|
+
upper1 = zd+posi1[0]+0.5*posi1[1]
|
|
1056
|
+
lower1 = zd+posi1[0]-0.5*posi1[1]
|
|
1057
|
+
u_mult1 = bgrid_weight(ind2,ind3,upper1)
|
|
1058
|
+
l_mult1 = bgrid_weight(ind2,ind3,lower1)
|
|
1059
|
+
min_mult = (jnp.abs(u_mult1-l_mult1)+u_mult1+l_mult1)/2
|
|
1060
|
+
|
|
1061
|
+
tot = tot.at[1].set(tot[1]+min_mult*0.5*k2*(mem_data[1]-new_zs[ind2,ind3,1])*(mem_data[1]-new_zs[ind2,ind3,1]))
|
|
1062
|
+
|
|
1063
|
+
def nbh_grad_calc3(tot,ind):
|
|
1064
|
+
inda,indb = unflat_ind(all_nbhs[ind],grid_size_x)
|
|
1065
|
+
def diff(tot):
|
|
1066
|
+
tot = tot.at[0].set(tot[0]+rpot_col(new_zs,inda,indb,ind2,ind3,0,zd,k))
|
|
1067
|
+
return tot
|
|
1068
|
+
def ndiff(tot):
|
|
1069
|
+
return tot
|
|
1070
|
+
tot = jax.lax.cond(jnp.logical_and(inda==ind2,indb==ind3),ndiff,diff,tot)
|
|
1071
|
+
return tot,ind
|
|
1072
|
+
tot,_ = jax.lax.scan(nbh_grad_calc3,tot,jnp.arange(all_nbhs.shape[0]))
|
|
1073
|
+
grad_grid = grad_grid.at[ind2,ind3].set(tot)
|
|
1074
|
+
return grad_grid,ind3
|
|
1075
|
+
grad_grid,_ = jax.lax.scan(nbh_grad_calc2,grad_grid,jnp.arange(grid_size_y))
|
|
1076
|
+
return grad_grid,ind2
|
|
1077
|
+
grad_grid,_ = jax.lax.scan(nbh_grad_calc1,grad_grid,jnp.arange(grid_size_x))
|
|
1078
|
+
return grad_grid
|
|
1079
|
+
|
|
1080
|
+
|
|
1081
|
+
#calculates the potential over all membrane segments
|
|
1082
|
+
@jax.jit
|
|
1083
|
+
def calc_graphs(xy,zd):
|
|
1084
|
+
xy = get_new_zs(xy,loop_inds)
|
|
1085
|
+
grid_vals = jnp.zeros((grid_size_x,grid_size_y,2))
|
|
1086
|
+
def calc_grid(grid_vals,ind):
|
|
1087
|
+
ind2 = ind
|
|
1088
|
+
def calc_grid2(grid_vals,ind):
|
|
1089
|
+
ind3 = ind
|
|
1090
|
+
z_disp = xy[ind2,ind3,0]+zd
|
|
1091
|
+
mt = xy[ind2,ind3,1]
|
|
1092
|
+
tot,_ = get_pot(ind2,ind3,xy[ind2,ind3,0],mt,zd)
|
|
1093
|
+
grid_vals = grid_vals.at[ind2,ind3].set(tot)
|
|
1094
|
+
return grid_vals,ind
|
|
1095
|
+
grid_vals,_ = jax.lax.scan(calc_grid2,grid_vals,jnp.arange(grid_size_y))
|
|
1096
|
+
return grid_vals,ind
|
|
1097
|
+
grid_vals,_ = jax.lax.scan(calc_grid,grid_vals,jnp.arange(grid_size_x))
|
|
1098
|
+
return grid_vals
|
|
1099
|
+
|
|
1100
|
+
#used for evaluating potential over all membrane segments for creating Potential graphs
|
|
1101
|
+
def get_pot_graph(in_xy):
|
|
1102
|
+
k = float(args.k1_const)
|
|
1103
|
+
k2 = float(args.k2_const)
|
|
1104
|
+
xy = in_xy[:grid_size_x*grid_size_y*2]
|
|
1105
|
+
zd = in_xy[-1]/5
|
|
1106
|
+
xy = xy.reshape((grid_size_x,grid_size_y,2))
|
|
1107
|
+
return calc_graphs(xy,zd)
|
|
1108
|
+
|
|
1109
|
+
#setting up the total potential function
|
|
1110
|
+
@jax.jit
|
|
1111
|
+
def total_pot_fun(in_xy):
|
|
1112
|
+
k = float(args.k1_const)
|
|
1113
|
+
k2 = float(args.k2_const)
|
|
1114
|
+
xy = in_xy[:grid_size_x*grid_size_y*2]
|
|
1115
|
+
zd = in_xy[-1]/5
|
|
1116
|
+
xy = xy.reshape((grid_size_x,grid_size_y,2))
|
|
1117
|
+
return jnp.sum(calc_graphs(xy,zd))+jnp.sum(nbh_calc(xy,k,k2,zd))
|
|
1118
|
+
|
|
1119
|
+
#differentiating using jax
|
|
1120
|
+
ac_grad_fun = jax.grad(total_pot_fun,argnums=0)
|
|
1121
|
+
|
|
1122
|
+
|
|
1123
|
+
#wrapping for use with numpy based minimisation algorithm (As the jax.numpy one had issues at time of writing - this could be updated once this works)
|
|
1124
|
+
def nwrap_tpot(in_xy):
|
|
1125
|
+
in_xyj = jnp.array(in_xy)
|
|
1126
|
+
return total_pot_fun(in_xyj)
|
|
1127
|
+
|
|
1128
|
+
def nwrap_grad(in_xy):
|
|
1129
|
+
in_xyj = jnp.array(in_xy)
|
|
1130
|
+
test = np.array(ac_grad_fun(in_xyj))
|
|
1131
|
+
return test
|
|
1132
|
+
|
|
1133
|
+
|
|
1134
|
+
|
|
1135
|
+
new_zs = jnp.zeros((grid_size_x,grid_size_y,2))
|
|
1136
|
+
new_zs = new_zs.at[:,:,1].set(mem_data[1])
|
|
1137
|
+
start_z = float(args.zshift)*5
|
|
1138
|
+
start_oz = 0
|
|
1139
|
+
|
|
1140
|
+
|
|
1141
|
+
print("Misc..")
|
|
1142
|
+
print("Done in:", str(np.format_float_positional(time.time()-timer,precision=3))+"s")
|
|
1143
|
+
print("Minimisation... (This will take a while)")
|
|
1144
|
+
|
|
1145
|
+
timer = time.time()
|
|
1146
|
+
|
|
1147
|
+
#writing bead positions for debugging purposes
|
|
1148
|
+
write_point(np.array(surf_poses),memdir+"Surface.pdb")
|
|
1149
|
+
write_point(np.array(all_poses),memdir+"All_beads.pdb")
|
|
1150
|
+
|
|
1151
|
+
#main minimisation loop
|
|
1152
|
+
try_again=True
|
|
1153
|
+
while try_again:
|
|
1154
|
+
min_out = minimize(nwrap_tpot, np.concatenate((np.array(new_zs.flatten()),np.array([start_z]))),jac = nwrap_grad ,method='BFGS', tol=2e-4,options={"gtol":0.002,"maxiter":iters})
|
|
1155
|
+
new_zs = min_out.x[:grid_size_x*grid_size_y*2]
|
|
1156
|
+
start_z = min_out.x[-1]
|
|
1157
|
+
new_zs = new_zs.reshape((grid_size_x,grid_size_y,2))
|
|
1158
|
+
new_zs = np.array(get_new_zs(jnp.array(new_zs),loop_inds))
|
|
1159
|
+
total_z = np.mean(new_zs[loop_inds_end[:,0],loop_inds_end[:,1],0])
|
|
1160
|
+
new_zs[:,:,0] -= total_z
|
|
1161
|
+
start_z += total_z*5
|
|
1162
|
+
if(min_out.status == 2):
|
|
1163
|
+
try_again = False
|
|
1164
|
+
elif(min_out.status == 1):
|
|
1165
|
+
try_again = False
|
|
1166
|
+
else:
|
|
1167
|
+
try_again=not min_out.success
|
|
1168
|
+
|
|
1169
|
+
|
|
1170
|
+
print("Done in:", str(np.format_float_positional(time.time()-timer,precision=3))+"s")
|
|
1171
|
+
|
|
1172
|
+
#calcuating graphs, contacts and general post processing
|
|
1173
|
+
print("Post processing...")
|
|
1174
|
+
timer = time.time()
|
|
1175
|
+
|
|
1176
|
+
np.savez(memdir+"Membrane_pos.npz",new_zs)
|
|
1177
|
+
np.savez(memdir+"Z_change.npz",start_z/5.0)
|
|
1178
|
+
np.savez(memdir+"Rotation_matrix.npz",rot_mat)
|
|
1179
|
+
|
|
1180
|
+
|
|
1181
|
+
bfacs = calc_contacts(jnp.array(new_zs),jnp.array(all_poses),start_z/5.0,xs,ys)
|
|
1182
|
+
bfacs_at = np.array(bfacs[1])
|
|
1183
|
+
bfacs_hg = np.array(bfacs[0])
|
|
1184
|
+
|
|
1185
|
+
bfacs_at /= np.max(bfacs_at)
|
|
1186
|
+
bfacs_hg /= np.max(bfacs_hg)
|
|
1187
|
+
|
|
1188
|
+
write_protein(bfacs_hg,fn,orient_dir+"HeadGroup_contacts.pdb")
|
|
1189
|
+
write_protein(bfacs_at,fn,orient_dir+"AcylTail_contacts.pdb")
|
|
1190
|
+
|
|
1191
|
+
|
|
1192
|
+
gc = calc_esf(start_z,new_zs,grid_ban,grid_size_x,grid_size_y,x_ext,y_ext,cposes,ctypes)
|
|
1193
|
+
potg = get_pot_graph(min_out.x)
|
|
1194
|
+
plt.imshow(potg[:,:,0])
|
|
1195
|
+
plt.savefig(orient_dir+"Potential_Upper.svg")
|
|
1196
|
+
plt.clf()
|
|
1197
|
+
plt.imshow(potg[:,:,1])
|
|
1198
|
+
plt.savefig(orient_dir+"Potential_Lower.svg")
|
|
1199
|
+
plt.clf()
|
|
1200
|
+
|
|
1201
|
+
|
|
1202
|
+
BotBan, TopBan = write_pdb(start_z,new_zs,grid_ban,grid_size_x,grid_size_y,x_ext,y_ext,gc,orient_dir,locdir,memdir,args.write_bfactors,mem_data,rot_mat_inv)
|
|
1203
|
+
|
|
1204
|
+
print("Z change:",np.format_float_positional(start_z/5.0,precision=3))
|
|
1205
|
+
plt.imshow((new_zs[:,:,0]+0.5*new_zs[:,:,1])*TopBan)
|
|
1206
|
+
plt.savefig(orient_dir+"Deformations_Upper.svg")
|
|
1207
|
+
plt.clf
|
|
1208
|
+
plt.imshow((new_zs[:,:,0]-0.5*new_zs[:,:,1])*BotBan)
|
|
1209
|
+
plt.savefig(orient_dir+"Deformations_Lower.svg")
|
|
1210
|
+
plt.clf
|
|
1211
|
+
|
|
1212
|
+
|
|
1213
|
+
|
|
1214
|
+
print("Done in:", str(np.format_float_positional(time.time()-timer,precision=3))+"s")
|
|
1215
|
+
|
|
1216
|
+
|
|
1217
|
+
|
|
1218
|
+
plt.imshow(gc[:,:,0]*BotBan)
|
|
1219
|
+
plt.savefig(orient_dir+"Charge_Lower.svg")
|
|
1220
|
+
plt.clf
|
|
1221
|
+
plt.imshow(gc[:,:,1]*TopBan)
|
|
1222
|
+
plt.savefig(orient_dir+"Charge_Upper.svg")
|
|
1223
|
+
plt.clf
|
|
1224
|
+
|
|
1225
|
+
|
|
1226
|
+
run_txt = open(orient_dir+"Run_command.txt","w")
|
|
1227
|
+
run_txt.write(" ".join(sys.argv))
|
|
1228
|
+
run_txt.close()
|
|
1229
|
+
|
|
1230
|
+
print("Total time:",str(np.format_float_positional(time.time()-tot_time,precision=3))+"s")
|
|
1231
|
+
|
|
1232
|
+
|
|
1233
|
+
if __name__ == "__main__":
|
|
1234
|
+
main()
|