99import os
1010
1111directory = '/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
1516with 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
2422def 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
2826def 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
3939def 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+
5671def 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
7395def 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
91113def 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
107132directory += res
108133file_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+
110152minrmsd = 20.0
111153
112154# Loop through files in the directory
113155for 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 )
279317else :
280318 with open ('no_matches.txt' ,'a' ) as outfile2 :
281- outfile2 .write (res )
319+ outfile2 .write (inp + ' \n ' )
0 commit comments