Skip to content

Commit 9beb968

Browse files
authored
Merge pull request #22 from libefp2/jack
modified: doc/applied_efp.rst
2 parents c0aaf40 + baa3f22 commit 9beb968

4 files changed

Lines changed: 132 additions & 90 deletions

File tree

doc/applied_efp.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ octupole, and polarization point sections. Sample execution:
244244

245245
``python make_MM.py shell_bchl361-79002.g96 bchl361-79002.g96 topol.top``
246246

247-
The topology file is necessary for atomic charges, and both structure files are read to so that only MM atoms will be
247+
The topology file is necessary for atomic charges, and both structure files are read so that only MM atoms will be
248248
included (both QM and EFP atoms are omitted).
249249

250250
Stripping QM atoms from EFP files

examples/flex-EFP/Scripts/fragment_RMSD.py

Lines changed: 94 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -9,65 +9,87 @@
99
import os
1010

1111
directory = '/depot/lslipche/data/yb_boss/flexible_efp/efpdb/'
12-
cutoff=0.15
12+
ang_cutoff=0.20 # Minimum RMSD allowed for "good" match
13+
cutoff=ang_cutoff*1.8897259886 # Cutoff convert to Bohr
1314

14-
inp=sys.argv[1]
15+
inp=sys.argv[1] # a_22_304.inp for example. Input file with fragment coords
1516
with open(inp, "r") as orig:
1617
orgs = orig.readlines()
17-
18-
efp=sys.argv[2]
19-
with open(efp, "r") as term:
20-
terms = term.readlines()
2118

22-
outname=inp.replace('.inp','.efp')
19+
outname=inp.replace('.inp','.efp') # Output file name, same as input but changed extension.
20+
# If no match is found, then outname will not be used.
2321

2422
def rotate_vector(vector, rotation_matrix):
2523
#Different from coords because dipoles assumed centered on coordinate. NOT placed in Cartesian space
26-
return np.dot(rotation_matrix, vector)
24+
return np.dot(vector,rotation_matrix)
2725

2826
def rotate_quadrupole(quadrupole, rotation_matrix):
29-
#RxQxR_t
27+
#R x Q x R_t
28+
#Quadrupoles are 3x3s. But .efp give only six values, order is assumed xx, xy, xz, yy, yz, zz
29+
#With symmetric off-diagonal elements.
3030
q = np.array([
31-
[quadrupole[0], quadrupole[1], quadrupole[2]],
32-
[quadrupole[1], quadrupole[3], quadrupole[4]],
33-
[quadrupole[2], quadrupole[4], quadrupole[5]],
31+
[quadrupole[0], quadrupole[3], quadrupole[4]],
32+
[quadrupole[3], quadrupole[1], quadrupole[5]],
33+
[quadrupole[4], quadrupole[5], quadrupole[2]],
3434
])
35-
q_rotated = rotation_matrix @ q @ rotation_matrix.T
36-
return [q_rotated[0, 0], q_rotated[0, 1], q_rotated[0, 2],
37-
q_rotated[1, 1], q_rotated[1, 2], q_rotated[2, 2]]
35+
q_rotated = rotation_matrix.T @ q @ rotation_matrix
36+
return [q_rotated[0, 0], q_rotated[1, 1], q_rotated[2, 2],
37+
q_rotated[0, 1], q_rotated[0, 2], q_rotated[1, 2]]
3838

3939
def rotate_octupole(octupole, rotation_matrix):
4040
#Oxyz=Rxi*Ryj*Rzk*Oijk summed over i=x,y,z;j=x,y,z;z=x,y,z;
4141
#Each term Oxyz of new tensor is composed of
4242
#27 pieces generated from old tensor and rotation matrix!
43+
#The indexes are hard-coded for some better readiability
4344
o = np.array([
44-
[[octupole[0], octupole[1], octupole[2]], [octupole[1], octupole[3], octupole[4]], [octupole[2], octupole[4], octupole[5]]],
45-
[[octupole[1], octupole[3], octupole[4]], [octupole[3], octupole[6], octupole[7]], [octupole[4], octupole[7], octupole[8]]],
46-
[[octupole[2], octupole[4], octupole[5]], [octupole[4], octupole[7], octupole[8]], [octupole[5], octupole[8], octupole[9]]],
45+
[[octupole[0], octupole[3], octupole[4]], [octupole[3], octupole[5], octupole[9]], [octupole[4], octupole[9], octupole[7]]],
46+
[[octupole[3], octupole[5], octupole[9]], [octupole[5], octupole[1], octupole[6]], [octupole[9], octupole[6], octupole[8]]],
47+
[[octupole[4], octupole[9], octupole[7]], [octupole[9], octupole[6], octupole[8]], [octupole[7], octupole[8], octupole[2]]],
4748
])
48-
o_rotated = np.einsum('ij,jkl,lm->ikm', rotation_matrix, o, rotation_matrix.T)
49+
#fancy function below does what we want. Look up np.einsum if you need clarification.
50+
#o_rotated = np.einsum('ij,jkl,lm->ikm', rotation_matrix, o, rotation_matrix.T)
51+
o_rotated = np.zeros((3, 3, 3))
52+
for p in range(0,3):
53+
for q in range(0,3):
54+
for r in range(0,3):
55+
o_rotated[p][q][r]=single_term_oct(p,q,r,o,rotation_matrix.T)
4956
return [
50-
o_rotated[0, 0, 0], o_rotated[0, 0, 1], o_rotated[0, 0, 2],
51-
o_rotated[0, 1, 1], o_rotated[0, 1, 2], o_rotated[0, 2, 2],
52-
o_rotated[1, 1, 1], o_rotated[1, 1, 2], o_rotated[1, 2, 2],
53-
o_rotated[2, 2, 2]
57+
o_rotated[0, 0, 0], o_rotated[1, 1, 1], o_rotated[2, 2, 2],
58+
o_rotated[0, 0, 1], o_rotated[0, 0, 2], o_rotated[0, 1, 1],
59+
o_rotated[1, 1, 2], o_rotated[0, 2, 2], o_rotated[1, 2, 2],
60+
o_rotated[0, 1, 2]
5461
]
5562

63+
def single_term_oct(p,q,r,octupole,rot_mat):
64+
term=0.0
65+
for i in range(0,3):
66+
for j in range(0,3):
67+
for k in range(0,3):
68+
term+=rot_mat[p][i]*rot_mat[q][j]*rot_mat[r][k]*octupole[i][j][k]
69+
return term
70+
5671
def rotate_polarizability(polarizability, rotation_matrix):
5772
#RxQxR_t
5873
q = np.array([
59-
[polarizability[0], polarizability[1], polarizability[2]],
60-
[polarizability[3], polarizability[4], polarizability[5]],
61-
[polarizability[6], polarizability[7], polarizability[8]],])
62-
q_rotated = rotation_matrix @ q @ rotation_matrix.T
63-
return q_rotated.flatten()
74+
[polarizability[0], polarizability[3], polarizability[4]],
75+
[polarizability[6], polarizability[1], polarizability[5]],
76+
[polarizability[7], polarizability[8], polarizability[2]]])
77+
q_rotated = rotation_matrix.T @ q @ rotation_matrix
78+
return [q_rotated[0, 0],q_rotated[1, 1],q_rotated[2, 2],
79+
q_rotated[0, 1],q_rotated[0, 2],q_rotated[1, 2],
80+
q_rotated[1, 0],q_rotated[2, 0],q_rotated[2, 1]]
81+
#return q_rotated.flatten()
6482

65-
def get_RMSD(coords1,coords2):
83+
def get_RMSD(coords1,coords2,mass):
6684
tot=0.0
67-
for i in range(3):
68-
for j in range(3):
69-
tot+=(coords1[i][j]-coords2[i][j])**2
70-
rmsd=np.sqrt((len(coords1)-1)*tot)
85+
length=len(coords1)
86+
dim=len(coords1[0])
87+
totmass=0.0
88+
for i in range(length):
89+
for j in range(dim):
90+
tot+=mass[i]*(coords1[i][j]-coords2[i][j])**2
91+
totmass+=mass[i]
92+
rmsd=np.sqrt(tot)/np.sqrt(totmass)
7193
return rmsd
7294

7395
def kabsch_algorithm(coords, coords2):
@@ -84,8 +106,8 @@ def kabsch_algorithm(coords, coords2):
84106
u, _, vh = np.linalg.svd(covariance_matrix)
85107
rotation_matrix = np.dot(u, vh)
86108

87-
if np.linalg.det(rotation_matrix) < 0:
88-
rotation_matrix[:, -1] *= -1
109+
#if np.linalg.det(rotation_matrix) < 0:
110+
# rotation_matrix[:, -1] *= -1
89111
return rotation_matrix, com1, com2
90112

91113
def apply_transform(coords, rotation_matrix, com1, com2):
@@ -100,39 +122,46 @@ def apply_transform(coords, rotation_matrix, com1, com2):
100122
'l':'leu','k':'lys','m':'met','f':'phe','p':'pro',
101123
's':'ser','t':'thr','w':'trp','y':'tyr','v':'val',
102124
'hp':'hip','hd':'hid','he':'hie'}
125+
atom_weights = {'H':1.0,'O':15.9949100,'C':12.0000000,'N':12.0030700,'S':32.0650000,'M':23.3040000}
103126

104-
105-
res=amino_acid_dict[inp[0]]
127+
try:
128+
res=amino_acid_dict[inp[0]]
129+
except:
130+
print('No library folder for: '+inp)
106131
#directory = '/depot/lslipche/data/yb_boss/flexible_efp/efpdb/'+res
107132
directory+=res
108133
file_extension = '.efp' # change this to your desired file extension
109134

135+
start=0
136+
xyz=[]
137+
orig_coords=[]
138+
weights=[]
139+
for line in orgs:
140+
if '$end' in line:
141+
start=0
142+
elif(start==1):
143+
xyz.append(float(line.split()[2])/0.529177249)
144+
xyz.append(float(line.split()[3])/0.529177249)
145+
xyz.append(float(line.split()[4])/0.529177249)
146+
orig_coords.append(xyz)
147+
xyz=[]
148+
weights.append(atom_weights[line.split()[0][0]])
149+
elif 'C1' in line:
150+
start=1
151+
110152
minrmsd=20.0
111153

112154
# Loop through files in the directory
113155
for filename in os.listdir(directory):
114156
if filename.endswith(file_extension):
115157
full_path = os.path.join(directory, filename)
116-
#full_path='ala0001.efp'
158+
#full_path=directory+'/gly5817.efp'
117159
#print(f"Processing file: {full_path}")
118160
with open(full_path, "r") as term:
119161
terms = term.readlines()
120162

121163
start=0
122164
xyz=[]
123-
orig_coords=[]
124-
for line in orgs:
125-
if '$end' in line:
126-
start=0
127-
elif(start==1):
128-
xyz.append(float(line.split()[2])/0.529177249)
129-
xyz.append(float(line.split()[3])/0.529177249)
130-
xyz.append(float(line.split()[4])/0.529177249)
131-
orig_coords.append(xyz)
132-
xyz=[]
133-
elif 'C1' in line:
134-
start=1
135-
start=0
136165
term_coords=[]
137166
for line in terms:
138167
if 'BO21' in line:
@@ -150,18 +179,27 @@ def apply_transform(coords, rotation_matrix, com1, com2):
150179
new_coords=np.array(term_coords)
151180
coords2=np.array(orig_coords)
152181
rotation_matrix, com1, com2 = kabsch_algorithm(new_coords, coords2)
153-
aligned_new_coords = apply_transform(new_coords, rotation_matrix, com1,com2,coords2)
154-
rmsd=(get_RMSD(aligned_new_coords,coords2))
182+
aligned_new_coords = apply_transform(new_coords, rotation_matrix, com1,com2)
183+
rmsd=(get_RMSD(aligned_new_coords,coords2,weights))
184+
#print(rmsd)
155185
if(rmsd<minrmsd):
156186
minrmsd=rmsd
157-
match=full_path
187+
if(rmsd<cutoff):
188+
match=full_path
189+
#break
190+
#print(minrmsd)
158191
#%%
159192

160193
#If good match found, transform that .efp to coords in .inp
161194
# Coords, dipoles, quadrupoles, octupoles, polarizable points and tensor
162195
# Monopoles and screen/screen2 do not need changed
163196

164-
if(minrmsd<cutoff):
197+
#print(rmsd/1.8897259886, full_path, inp)
198+
#print(get_RMSD(aligned_new_coords,coords2,weights))
199+
#print(aligned_new_coords)
200+
#print(coords2)
201+
202+
if(rmsd<cutoff):
165203
with open(match, "r") as efp:
166204
f0 = efp.readlines()
167205
start=0
@@ -278,4 +316,4 @@ def apply_transform(coords, rotation_matrix, com1, com2):
278316
outfile.write(line1)
279317
else:
280318
with open('no_matches.txt','a') as outfile2:
281-
outfile2.write(res)
319+
outfile2.write(inp+'\n')

examples/flex-EFP/Scripts/make_AAs.py

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,38 +12,29 @@
1212
import numpy as np
1313
import sys
1414

15-
#efp_g96='shell_bchl361-79002.g96'
15+
#efp_g96='efp_pair53004.g96'
1616
efp_g96=sys.argv[1]
1717
with open(efp_g96, 'r') as inp:
1818
f0 = inp.readlines()
1919

20-
#full_g96='bchl361-79002.g96'
20+
#full_g96='confout_pair53004.g96'
2121
full_g96=sys.argv[2]
2222
with open(full_g96, 'r') as g96:
2323
g0 = g96.readlines()
2424

25-
#settings_file='user_set.txt'
25+
#settings_file='user_defined.txt'
2626
settings_file=sys.argv[3]
2727

28-
#topol_file='topol.top'
28+
#topol_file='edit_topol.itp'
2929
topol_file=sys.argv[4]
3030

3131
# Data and parameters
32-
Rings = [
33-
'MG', 'CHA', 'CHB', 'HB', 'CHC', 'HC', 'CHD', 'HD', 'NA', 'C1A', 'C2A', 'H2A', 'C3A', 'H3A',
34-
'C4A', 'CMA', 'HMA1', 'HMA2', 'HMA3', 'NB', 'C1B', 'C2B', 'C3B', 'C4B', 'CMB', 'HMB1',
35-
'HMB2', 'HMB3', 'CAB', 'OBB', 'CBB', 'HBB1', 'HBB2', 'HBB3', 'NC', 'C1C', 'C2C', 'H2C',
36-
'C3C', 'H3C', 'C4C', 'CMC', 'HMC1', 'HMC2', 'HMC3', 'CAC', 'HAC1', 'HAC2', 'CBC', 'HBC1',
37-
'HBC2', 'HBC3', 'ND', 'C1D', 'C2D', 'C3D', 'C4D', 'CMD', 'HMD1', 'HMD2', 'HMD3', 'CAD',
38-
'OBD', 'CBD', 'HBD', 'CGD', 'O1D', 'O2D', 'CED', 'HED1', 'HED2', 'HED3'
39-
]
4032

33+
#Charges of residues. NVAL and CGLN should be redundant, now. New logic assumes and N-terminal is +1 and
34+
# any C-terminal is -1. spec_AAs are residues that have non-zero charge, AA-charge is the dictionary with
35+
#that non-zero charge.
4136
AA_charge = {'ASP': '-1', 'GLU': '-1', 'NVAL': '1', 'HIP': '1', 'LYS': '1', 'ARG': '1', 'CGLN': '-1'}
4237
spec_AAs = ['ASP', 'GLU', 'NVAL', 'HIP', 'LYS', 'ARG', 'CGLN']
43-
CLA_resids = [
44-
'359', '360', '361', '362', '363', '364', '365', '366', '725', '726', '727', '728', '729', '730', '731', '732',
45-
'1091', '1092', '1093', '1094', '1095', '1096', '1097', '1098'
46-
]
4738

4839
amino_acid_dict = {
4940
'ALA': 'a', 'ARG': 'r', 'ASN': 'n', 'ASP': 'd', 'CYS': 'c', 'GLN': 'q', 'GLU': 'e', 'GLY': 'g', 'HIS': 'h',
@@ -110,6 +101,11 @@ def make_inp(fragment, QMs, POLs):
110101
return
111102
if fragment[4].split()[1] in spec_AAs:
112103
charge = AA_charge[fragment[4].split()[1]]
104+
elif len(fragment[4].split()[1])==4:
105+
if(fragment[4].split()[1][0]=='N'):
106+
charge=1
107+
elif(fragment[4].split()[1][0]=='C'):
108+
charge=-1
113109
else:
114110
charge = '0'
115111

@@ -271,7 +267,9 @@ def QM_MM_covalent(MM,QMs,topol_file):
271267

272268
if line.split()[0] == efp_resis[i]:
273269
if len(prev_co) > 1 and line.split()[1] in known_amino_acids:
274-
frag.extend(prev_co)
270+
#frag.extend(prev_co)
271+
frag.append(prev_co[-2])
272+
frag.append(prev_co[-1])
275273
prev_co = []
276274
frag.append(line)
277275
elif 'POSITION' in line:

examples/flex-EFP/Scripts/make_bcls.py

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,16 @@
99
"""
1010

1111
import numpy as np
12-
import sys
1312

1413
#site='359'
15-
g96_file=sys.argv[1]
16-
site=sys.argv[2]
14+
#g96_file=sys.argv[1]
15+
g96_file='efp_pair53004.g96'
16+
#site=sys.argv[2]
17+
18+
tailside='C6'
19+
headside='C5'
20+
site=['752','754']
21+
oldres='752'
1722

1823
def cut_frag(head,tail):
1924
desired_dist=1.07886
@@ -31,7 +36,7 @@ def cut_frag(head,tail):
3136

3237
def make_inp(fragment):
3338
txt=[]
34-
filename='t_'+fragment[0].split()[0]+'.inp'
39+
filename='cla_t_'+fragment[0].split()[0]+'.inp'
3540
txt.append(' $contrl units=angs local=boys runtyp=makefp \n'+
3641
' mult=1 icharg=0 coord=cart icut=11 $end\n'+
3742
' $system timlim=99999 mwords=200 $end\n'+
@@ -49,7 +54,7 @@ def make_inp(fragment):
4954
if(atom.split()[2][0]=='M'):
5055
col1=' '+atom.split()[2][0:2]+atom.split()[3]+' '
5156
col2=at_sym['MG']
52-
filename='h_'+atom.split()[0]+'.inp'
57+
filename='cla_h_'+atom.split()[0]+'.inp'
5358
else:
5459
col1=' '+atom.split()[2][0]+atom.split()[3]+' '
5560
col2=at_sym[atom.split()[2][0]]
@@ -77,32 +82,33 @@ def make_inp(fragment):
7782
'NA':'11.0','CL':'17.0'
7883
}
7984

80-
Rings=['MG','CHA','CHB','HB','CHC','HC','CHD','HD','NA','C1A','C2A','H2A','C3A','H3A','C4A',
81-
'CMA','HMA1','HMA2','HMA3','NB','C1B','C2B','C3B','C4B','CMB','HMB1','HMB2','HMB3',
82-
'CAB','OBB','CBB','HBB1','HBB2','HBB3','NC','C1C','C2C','H2C','C3C','H3C','C4C',
83-
'CMC','HMC1','HMC2','HMC3','CAC','HAC1','HAC2','CBC','HBC1','HBC2','HBC3','ND',
84-
'C1D','C2D','C3D','C4D','CMD','HMD1','HMD2','HMD3','CAD','OBD','CBD','HBD','CGD',
85-
'O1D','O2D','CED','HED1','HED2','HED3']
85+
Rings=['MG','CHA','CHB','CHC','CHD','NA','C1A','C2A','C3A','C4A','CMA','NB','C1B','C2B','C3B',
86+
'C4B','CMB','CAB','CBB','NC','C1C','C2C','C3C','C4C','CMC','CAC','CBC','ND','C1D','C2D',
87+
'C3D','C4D','CMD','CAD','OBD','CBD','CGD','O1D','O2D','CED','CAA','CBA','CGA','O1A',
88+
'O2A','C1','C2','C3','C4','C5','H1','H2','H3','H4','H5','H6','H7','H8','H9','H10','H11',
89+
'H12','H13','H14','H15','H16','H17','H18','H19','H20','H21','H22','H23','H24','H25',
90+
'H26','H27','H28','H29','H30','H31','H32','H33','H34','H35','H36','H37','H38','H39',
91+
'H40','H41']
8692

8793
#with open('bchl359-50028.g96','r') as g96:
8894
# g0=g96.readlines()
8995

9096
with open(g96_file,'r') as g96:
9197
g0=g96.readlines()
9298

93-
tailside='CAA'
94-
headside='C2A'
99+
#tailside and headside represent the atoms that are bound but are to be broken to create
100+
#separate fragment files.
95101
curr_head=[]
96102
curr_tail=[]
97103
#BCLs=[]
98-
oldres='359'
99104
for line in g0:
100-
if 'BCL' in line:
105+
if 'CLA' in line:
101106
if(oldres!=line.split()[0]):
102107
head_coord,tail_coord = cut_frag(head_cut,tail_cut)
103108
curr_head.append(' H000 1.0 '+str("{:.8f}".format(head_coord[0]))+' '+str("{:.8f}".format(head_coord[1]))+' '+str("{:.8f}".format(head_coord[2]))+'\n')
104109
curr_tail.append(' H000 1.0 '+str("{:.8f}".format(tail_coord[0]))+' '+str("{:.8f}".format(tail_coord[1]))+' '+str("{:.8f}".format(tail_coord[2]))+'\n')
105-
if(oldres!=site):
110+
#if(oldres!=site):
111+
if oldres not in site:
106112
make_inp(curr_head)
107113
make_inp(curr_tail)
108114
curr_head=[]

0 commit comments

Comments
 (0)