1
2
3
4
5
6
7 from Numeric import *
8 import math
9
10
11
12
13
14
15
17 res = array([ v1[1]*v2[2] - v1[2]*v2[1],
18 -v1[0]*v2[2] + v1[2]*v2[0],
19 v1[0]*v2[1] - v1[1]*v2[0]],Float)
20 return res
21
23 """
24 Find the IDs of the neighboring atom IDs
25
26 ARGUMENTS:
27 atomId - atom of interest
28 adjMat - adjacency matrix for the compound
29 """
30 nbrs = []
31 for i,nid in enumerate(adjMat[atomId]):
32 if nid >= 1 :
33 nbrs.append(i)
34 return nbrs
35
37
38
39
40 cpt = array(coords[3*center:3*center+3])
41 avgVec = 0
42 for nid in nbrs:
43 pt = array(coords[3*nid:3*nid+3])
44 pt -= cpt
45 pt /= (sqrt(innerproduct(pt, pt)))
46 if (avgVec == 0) :
47 avgVec = pt
48 else :
49 avgVec += pt
50
51 avgVec /= (sqrt(innerproduct(avgVec, avgVec)))
52 return avgVec
53
55 """
56 Compute the direction vector for an aromatic feature
57
58 ARGUMENTS:
59 coords - an list of atom coordinates the format is [x1, y1, z1, x2, y2, z3 ....]
60 featAtoms - list of atom IDs that make up the feature
61 featLoc - location of the aromatic feature specified as a numeric array
62 scale - the size of the direction vector
63 """
64 dirType = 'linear'
65 head = featLoc
66 ats = [coords[3*(x):3*(x)+3] for x in featAtoms]
67
68 p0 = array(ats[0])
69 p1 = array(ats[1])
70 v1 = p0-head
71 v2 = p1-head
72 norm1 = cross(v1,v2)
73 norm1 = norm1/sqrt(innerproduct(norm1,norm1))
74 norm1 *= scale
75 norm2 = -norm1
76 norm1 += head
77 norm2 += head
78 return ( (head,norm1),(head,norm2) ), dirType
79
81 theta = math.pi*theta/180
82 c = math.cos(theta)
83 s = math.sin(theta)
84 t = 1-c
85 X = ax[0]
86 Y = ax[1]
87 Z = ax[2]
88 mat = [ [t*X*X+c, t*X*Y+s*Z, t*X*Z-s*Y],
89 [t*X*Y-s*Z,t*Y*Y+c,t*Y*Z+s*X],
90 [t*X*Z+s*Y,t*Y*Z-s*X,t*Z*Z+c] ]
91 mat = array(mat)
92 return matrixmultiply(mat,pt)
93
95 """
96 Get the direction vectors for Acceptor of type 2
97
98 This is the acceptor with two adjacent heavy atoms. We will special case a few things here.
99 If the acceptor atom is an oxygen we will assume a sp3 hybridization
100 the acceptor directions (two of them)
101 reflect that configurations. Otherwise the direction vector in plane with the neighboring
102 heavy atoms
103
104 ARGUMENTS:
105 coords - an list of atom coordinates the format is [x1, y1, z1, x2, y2, z3 ....]
106 adjMat - adjacency martix of the compound
107 featAtoms - list of atoms that are part of the feature
108 scale - length of the direction vector
109 """
110 assert len(featAtoms) == 1
111 aid = featAtoms[0]
112 cpt = array(coords[3*aid:3*aid+3])
113 nbrs = findNeighbors(aid, adjMat)
114 assert len(nbrs) == 2
115
116 bvec = _findAvgVec(coords, aid, nbrs)
117 bvec *= (-1.0*scale)
118
119
120 if (atomNames[aid] == 'O') :
121
122
123 v1 = array(coords[3*nbrs[0]:3*nbrs[0]+3])
124 v1 -= cpt
125 v2 = array(coords[3*nbrs[1]:3*nbrs[1]+3])
126 v2 -= cpt
127 rotAxis = v1 - v2
128 rotAxis /= sqrt(innerproduct(rotAxis, rotAxis))
129 bv1 = ArbAxisRotation(54.5, rotAxis, bvec)
130 bv1 += cpt
131 bv2 = ArbAxisRotation(-54.5, rotAxis, bvec)
132 bv2 += cpt
133 return ((cpt, bv1), (cpt, bv2),), 'linear'
134 else :
135 bvec += cpt
136 return ((cpt, bvec),), 'linear'
137
139 """
140 Get the direction vectors for Donor of type 3
141
142 This is a donor with three heavy atoms as neighbors. We will assume
143 a tetrahedral arrangement of these neighbors. So the direction we are seeking
144 is the last fourth arm of the sp3 arrangment
145
146 ARGUMENTS:
147 coords - an list of atom coordinates the format is [x1, y1, z1, x2, y2, z3 ....]
148 adjMat - adjacency martix of the compound
149 featAtoms - list of atoms that are part of the feature
150 scale - length of the direction vector
151 """
152 assert len(featAtoms) == 1
153 aid = featAtoms[0]
154 cpt = array(coords[3*aid:3*aid+3])
155 nbrs = findNeighbors(aid, adjMat)
156
157 bvec = _findAvgVec(coords, aid, nbrs)
158 bvec *= (-1.0*scale)
159 bvec += cpt
160 return ((cpt, bvec),), 'linear'
161
163 hAtoms = []
164 for nid in nbrs:
165 if atomNames[nid] == 'H':
166 hAtoms.append(nid)
167 return hAtoms
168
170 assert len(nbrs) == 3
171 cpt = array(coords[3*center:3*center+3])
172 v1 = array(coords[3*nbrs[0]:3*nbrs[0]+3])
173 v1 -= cpt
174 v2 = array(coords[3*nbrs[1]:3*nbrs[1]+3])
175 v2 -= cpt
176 v3 = array(coords[3*nbrs[2]:3*nbrs[2]+3])
177 v3 -= cpt
178 normal = cross(v1,v2)
179 dotP = abs(innerproduct(v3, normal))
180
181 if (dotP <= tol) :
182 return 1
183 else :
184 return 0
185
187 """
188 Get the direction vectors for Donor of type 2
189
190 This is a donor with two heavy atoms as neighbors. The atom may are may not have
191 hydrogen on it. Here are the situations with the neighbors that will be considered here
192 1. two heavy atoms and two hydrogens: we will assume a sp3 arrangement here
193 2. two heavy atoms and one hydrogen: this can either be sp2 or sp3
194 3. two heavy atoms and no hydrogens
195
196 ARGUMENTS:
197 coords - an list of atom coordinates the format is [x1, y1, z1, x2, y2, z3 ....]
198 adjMat - adjacency martix of the compound
199 atomNames - element names of the atoms in the compound
200 featAtoms - list of atoms that are part of the feature
201 scale - length of the direction vector
202 """
203
204 assert len(featAtoms) == 1
205 aid = featAtoms[0]
206 cpt = array(coords[3*aid:3*aid+3])
207
208 nbrs = findNeighbors(aid, adjMat)
209 assert len(nbrs) >= 2
210
211 hydrogens = _findHydAtoms(nbrs, atomNames)
212
213 if len(nbrs) == 2:
214
215 assert len(hydrogens) == 0
216
217 bvec = _findAvgVec(coords, aid, nbrs)
218 bvec *= (-1.0*scale)
219 bvec += cpt
220 return ((cpt, bvec),), 'linear'
221
222 elif len(nbrs) == 3:
223 assert len(hydrogens) == 1
224
225
226
227
228 hid = hydrogens[0]
229 bvec = array(coords[3*hid:3*hid+3])
230 bvec -= cpt
231 bvec /= (sqrt(innerproduct(bvec, bvec)))
232 bvec *= scale
233 bvec += cpt
234 if _checkPlanarity(coords, aid, nbrs):
235
236 return ((cpt, bvec),), 'linear'
237 else :
238
239 ovec = _findAvgVec(coords, aid, nbrs)
240 ovec *= (-1.0*scale)
241 ovec += cpt
242 return ((cpt, bvec), (cpt, ovec),), 'linear'
243
244 elif len(nbrs) >= 4 :
245
246 res = []
247 for hid in hydrogenss:
248 bvec = array(coords[3*(hid):3*hid+3])
249 bvec -= cpt
250 bvec /= (sqrt(innerproduct(bvec, bvec)))
251 bvec *= scale
252 bvec += cpt
253 res.append((cpt, bvec))
254 return tuple(res), 'linear'
255
257 """
258 Get the direction vectors for Donor of type 1
259
260 This is a donor with one heavy atom. It is not clear where we should we should be putting the
261 direction vector for this. It should probably be a cone. In this case we will just use the
262 direction vector from the donor atom to the heavy atom
263
264 ARGUMENTS:
265 coords - an list of atom coordinates the format is [x1, y1, z1, x2, y2, z3 ....]
266 adjMat - adjacency martix of the compound
267 atomNames - element names of the atoms in the compound
268 featAtoms - list of atoms that are part of the feature
269 scale - length of the direction vector
270 """
271 assert len(featAtoms) == 1
272 aid = featAtoms[0]
273 nbrs = findNeighbors(aid, adjMat)
274
275
276 hnbr = -1
277 for nid in nbrs:
278 if atomNames[nid] != 'H':
279 hnbr = nid
280 break
281
282 cpt = array(coords[3*aid:3*aid+3])
283 v1 = array(coords[3*hnbr:3*hnbr+3])
284 v1 -= cpt
285 v1 /= (sqrt(innerproduct(v1, v1)))
286 v1 *= (-1.0*scale)
287 v1 += cpt
288 return ((cpt, v1),), 'cone'
289
291 """
292 Get the direction vectors for Acceptor of type 1
293
294 This is a acceptor with one heavy atom neighbor. There are two possibilities we will
295 consider here
296 1. The bond to the heavy atom is a single bond e.g. CO
297 In this case we don't know the exact direction and we just use the inversion of this bond direction
298 and mark this direction as a 'cone'
299 2. The bond to the heavy atom is a double bond e.g. C=O
300 In this case the we have two possible direction except in some special cases e.g. SO2
301 where again we will use bond direction
302
303 ARGUMENTS:
304 coords - an list of atom coordinates the format is [x1, y1, z1, x2, y2, z3 ....]
305 adjMat - adjacency martix of the compound
306 atomNames - element names of the atoms in the compound
307 featAtoms - list of atoms that are part of the feature
308 scale - length of the direction vector
309 """
310 assert len(featAtoms) == 1
311 aid = featAtoms[0]
312 nbrs = findNeighbors(aid, adjMat)
313 cpt = array(coords[3*aid:3*aid+3])
314
315 heavyAt = -1
316 for nbr in nbrs:
317 if atomNames[nbr] != 'H':
318 heavyAt = nbr
319 break
320
321 singleBnd = 1
322 if adjMat[aid][heavyAt] >= 1.5:
323 singleBnd = 0
324
325
326 sulfer = 0
327 if atomNames[heavyAt] == 'S':
328 sulfer = 1
329
330 if singleBnd or sulfer:
331 v1 = array(coords[3*heavyAt:3*heavyAt+3])
332 v1 -= cpt
333 v1 /= (sqrt(innerproduct(v1, v1)))
334 v1 *= (-1.0*scale)
335 v1 += cpt
336 return ((cpt, v1),), 'cone'
337
338 else :
339
340
341
342
343 hvNbrs = findNeighbors(heavyAt, adjMat)
344 hvNbr = -1
345 for nbr in hvNbrs:
346 if (nbr != aid) :
347 hvNbr = nbr
348 break
349
350 pt1 = array(coords[3*hvNbr:3*hvNbr+3])
351 v1 = array(coords[3*heavyAt:3*heavyAt+3])
352 pt1 -= v1
353 v1 -= cpt
354 rotAxis = cross(v1, pt1)
355 rotAxis /= sqrt(innerproduct(rotAxis, rotAxis))
356 bv1 = ArbAxisRotation(120, rotAxis, v1)
357 bv1 /= sqrt(innerproduct(bv1, bv1))
358 bv1 *= scale
359 bv1 += cpt
360 bv2 = ArbAxisRotation(-120, rotAxis, v1)
361 bv2 /= sqrt(innerproduct(bv2, bv2))
362 bv2 *= scale
363 bv2 += cpt
364 return ((cpt, bv1), (cpt, bv2),), 'linear'
365