1
2
3
4
5
6
7 from rdkit import Geometry
8 from rdkit import Chem
9 import numpy
10 import math
11
12
13
14
15
16
17
19 res = numpy.array([ v1[1]*v2[2] - v1[2]*v2[1],
20 -v1[0]*v2[2] + v1[2]*v2[0],
21 v1[0]*v2[1] - v1[1]*v2[0]],numpy.double)
22 return res
23
25 """
26 Find the IDs of the neighboring atom IDs
27
28 ARGUMENTS:
29 atomId - atom of interest
30 adjMat - adjacency matrix for the compound
31 """
32 nbrs = []
33 for i,nid in enumerate(adjMat[atomId]):
34 if nid >= 1 :
35 nbrs.append(i)
36 return nbrs
37
39
40
41
42 avgVec = 0
43 for nbr in nbrs:
44 nid = nbr.GetIdx()
45 pt = conf.GetAtomPosition(nid)
46 pt -= center
47 pt.Normalize()
48 if (avgVec == 0) :
49 avgVec = pt
50 else :
51 avgVec += pt
52
53 avgVec.Normalize()
54 return avgVec
55
57 """
58 Compute the direction vector for an aromatic feature
59
60 ARGUMENTS:
61 conf - a conformer
62 featAtoms - list of atom IDs that make up the feature
63 featLoc - location of the aromatic feature specified as point3d
64 scale - the size of the direction vector
65 """
66 dirType = 'linear'
67 head = featLoc
68 ats = [conf.GetAtomPosition(x) for x in featAtoms]
69
70 p0 = ats[0]
71 p1 = ats[1]
72 v1 = p0-head
73 v2 = p1-head
74 norm1 = v1.CrossProduct(v2)
75 norm1.Normalize()
76 norm1 *= scale
77
78 norm2 = head-norm1
79 norm1 += head
80 return ( (head,norm1),(head,norm2) ), dirType
81
83 theta = math.pi*theta/180
84 c = math.cos(theta)
85 s = math.sin(theta)
86 t = 1-c
87 X = ax.x
88 Y = ax.y
89 Z = ax.z
90 mat = [ [t*X*X+c, t*X*Y+s*Z, t*X*Z-s*Y],
91 [t*X*Y-s*Z,t*Y*Y+c,t*Y*Z+s*X],
92 [t*X*Z+s*Y,t*Y*Z-s*X,t*Z*Z+c] ]
93 mat = numpy.array(mat)
94 if isinstance(pt,Geometry.Point3D):
95 pt = numpy.array((pt.x,pt.y,pt.z))
96 tmp = numpy.dot(mat,pt)
97 res=Geometry.Point3D(tmp[0],tmp[1],tmp[2])
98 elif isinstance(pt,list) or isinstance(pt,tuple):
99 pts = pt
100 res = []
101 for pt in pts:
102 pt = numpy.array((pt.x,pt.y,pt.z))
103 tmp = numpy.dot(mat,pt)
104 res.append(Geometry.Point3D(tmp[0],tmp[1],tmp[2]))
105 else:
106 res=None
107 return res
108
109
110
111
112
114 """
115 Get the direction vectors for Acceptor of type 2
116
117 This is the acceptor with two adjacent heavy atoms. We will special case a few things here.
118 If the acceptor atom is an oxygen we will assume a sp3 hybridization
119 the acceptor directions (two of them)
120 reflect that configurations. Otherwise the direction vector in plane with the neighboring
121 heavy atoms
122
123 ARGUMENTS:
124 featAtoms - list of atoms that are part of the feature
125 scale - length of the direction vector
126 """
127 assert len(featAtoms) == 1
128 aid = featAtoms[0]
129 cpt = conf.GetAtomPosition(aid)
130
131 mol = conf.GetOwningMol()
132 nbrs = list(mol.GetAtomWithIdx(aid).GetNeighbors())
133 hydrogens = []
134 tmp=[]
135 while len(nbrs):
136 nbr = nbrs.pop()
137 if nbr.GetAtomicNum()==1:
138 hydrogens.append(nbr)
139 else:
140 tmp.append(nbr)
141 nbrs = tmp
142 assert len(nbrs) == 2
143
144 bvec = _findAvgVec(conf, cpt, nbrs)
145 bvec *= (-1.0*scale)
146
147 if (mol.GetAtomWithIdx(aid).GetAtomicNum()==8):
148
149
150 v1 = conf.GetAtomPosition(nbrs[0].GetIdx())
151 v1 -= cpt
152 v2 = conf.GetAtomPosition(nbrs[1].GetIdx())
153 v2 -= cpt
154 rotAxis = v1 - v2
155 rotAxis.Normalize()
156 bv1 = ArbAxisRotation(54.5, rotAxis, bvec)
157 bv1 += cpt
158 bv2 = ArbAxisRotation(-54.5, rotAxis, bvec)
159 bv2 += cpt
160 return ((cpt, bv1), (cpt, bv2),), 'linear'
161 else :
162 bvec += cpt
163 return ((cpt, bvec),), 'linear'
164
178
180 """
181 Get the direction vectors for Donor of type 3
182
183 This is a donor with three heavy atoms as neighbors. We will assume
184 a tetrahedral arrangement of these neighbors. So the direction we are seeking
185 is the last fourth arm of the sp3 arrangment
186
187 ARGUMENTS:
188 featAtoms - list of atoms that are part of the feature
189 scale - length of the direction vector
190 """
191 assert len(featAtoms) == 1
192 aid = featAtoms[0]
193
194 tfv = _GetTetrahedralFeatVect(conf,aid,scale)
195 return tfv, 'linear'
196
198 """
199 Get the direction vectors for Donor of type 3
200
201 This is a donor with three heavy atoms as neighbors. We will assume
202 a tetrahedral arrangement of these neighbors. So the direction we are seeking
203 is the last fourth arm of the sp3 arrangment
204
205 ARGUMENTS:
206 featAtoms - list of atoms that are part of the feature
207 scale - length of the direction vector
208 """
209 assert len(featAtoms) == 1
210 aid = featAtoms[0]
211 tfv = _GetTetrahedralFeatVect(conf,aid,scale)
212 return tfv, 'linear'
213
215 hAtoms = []
216 for nid in nbrs:
217 if atomNames[nid] == 'H':
218 hAtoms.append(nid)
219 return hAtoms
220
235
237 """
238 Get the direction vectors for Donor of type 2
239
240 This is a donor with two heavy atoms as neighbors. The atom may are may not have
241 hydrogen on it. Here are the situations with the neighbors that will be considered here
242 1. two heavy atoms and two hydrogens: we will assume a sp3 arrangement here
243 2. two heavy atoms and one hydrogen: this can either be sp2 or sp3
244 3. two heavy atoms and no hydrogens
245
246 ARGUMENTS:
247 featAtoms - list of atoms that are part of the feature
248 scale - length of the direction vector
249 """
250 assert len(featAtoms) == 1
251 aid = featAtoms[0]
252 mol = conf.GetOwningMol()
253
254 cpt = conf.GetAtomPosition(aid)
255
256
257 nbrs = list(mol.GetAtomWithIdx(aid).GetNeighbors())
258 assert len(nbrs) >= 2
259
260 hydrogens = []
261 tmp=[]
262 while len(nbrs):
263 nbr = nbrs.pop()
264 if nbr.GetAtomicNum()==1:
265 hydrogens.append(nbr)
266 else:
267 tmp.append(nbr)
268 nbrs = tmp
269
270 if len(nbrs) == 2:
271
272 assert len(hydrogens) == 0
273
274 bvec = _findAvgVec(conf, cpt, nbrs)
275 bvec *= (-1.0*scale)
276 bvec += cpt
277 return ((cpt, bvec),), 'linear'
278 elif len(nbrs) == 3:
279 assert len(hydrogens) == 1
280
281
282
283
284 hid = hydrogens[0].GetIdx()
285 bvec = conf.GetAtomPosition(hid)
286 bvec -= cpt
287 bvec.Normalize()
288 bvec *= scale
289 bvec += cpt
290 if _checkPlanarity(conf, cpt, nbrs):
291
292 return ((cpt, bvec),), 'linear'
293 else :
294
295 ovec = _findAvgVec(conf, cpt, nbrs)
296 ovec *= (-1.0*scale)
297 ovec += cpt
298 return ((cpt, bvec), (cpt, ovec),), 'linear'
299
300 elif len(nbrs) >= 4 :
301
302 res = []
303 for hid in hydrogenss:
304 bvec = numpy.array(coords[3*(hid):3*hid+3])
305 bvec -= cpt
306 bvec /= (numpy.sqrt(numpy.dot(bvec, bvec)))
307 bvec *= scale
308 bvec += cpt
309 res.append((cpt, bvec))
310 return tuple(res), 'linear'
311
313 """
314 Get the direction vectors for Donor of type 1
315
316 This is a donor with one heavy atom. It is not clear where we should we should be putting the
317 direction vector for this. It should probably be a cone. In this case we will just use the
318 direction vector from the donor atom to the heavy atom
319
320 ARGUMENTS:
321
322 featAtoms - list of atoms that are part of the feature
323 scale - length of the direction vector
324 """
325 assert len(featAtoms) == 1
326 aid = featAtoms[0]
327 mol = conf.GetOwningMol()
328 nbrs = mol.GetAtomWithIdx(aid).GetNeighbors()
329
330
331 hnbr = -1
332 for nbr in nbrs:
333 if nbr.GetAtomicNum()!=1:
334 hnbr = nbr.GetIdx()
335 break
336
337 cpt = conf.GetAtomPosition(aid)
338 v1 = conf.GetAtomPosition(hnbr)
339 v1 -= cpt
340 v1.Normalize()
341 v1 *= (-1.0*scale)
342 v1 += cpt
343 return ((cpt, v1),), 'cone'
344
346 """
347 Get the direction vectors for Acceptor of type 1
348
349 This is a acceptor with one heavy atom neighbor. There are two possibilities we will
350 consider here
351 1. The bond to the heavy atom is a single bond e.g. CO
352 In this case we don't know the exact direction and we just use the inversion of this bond direction
353 and mark this direction as a 'cone'
354 2. The bond to the heavy atom is a double bond e.g. C=O
355 In this case the we have two possible direction except in some special cases e.g. SO2
356 where again we will use bond direction
357
358 ARGUMENTS:
359 featAtoms - list of atoms that are part of the feature
360 scale - length of the direction vector
361 """
362 assert len(featAtoms) == 1
363 aid = featAtoms[0]
364 mol = conf.GetOwningMol()
365 nbrs = mol.GetAtomWithIdx(aid).GetNeighbors()
366
367 cpt = conf.GetAtomPosition(aid)
368
369
370 heavyAt = -1
371 for nbr in nbrs:
372 if nbr.GetAtomicNum()!=1:
373 heavyAt = nbr
374 break
375
376 singleBnd = mol.GetBondBetweenAtoms(aid,heavyAt.GetIdx()).GetBondType() > Chem.BondType.SINGLE
377
378
379 sulfur = heavyAt.GetAtomicNum()==16
380
381 if singleBnd or sulfur:
382 v1 = conf.GetAtomPosition(heavyAt.GetIdx())
383 v1 -= cpt
384 v1.Normalize()
385 v1 *= (-1.0*scale)
386 v1 += cpt
387 return ((cpt, v1),), 'cone'
388 else :
389
390
391
392
393 hvNbrs = heavyAt.GetNeighbors()
394 hvNbr = -1
395 for nbr in hvNbrs:
396 if nbr.GetIdx() != aid:
397 hvNbr = nbr
398 break
399
400 pt1 = conf.GetAtomPosition(hvNbr.GetIdx())
401 v1 = conf.GetAtomPosition(heavyAt.GetIdx())
402 pt1 -= v1
403 v1 -= cpt
404 rotAxis = v1.CrossProduct(pt1)
405 rotAxis.Normalize()
406 bv1 = ArbAxisRotation(120, rotAxis, v1)
407 bv1.Normalize()
408 bv1 *= scale
409 bv1 += cpt
410 bv2 = ArbAxisRotation(-120, rotAxis, v1)
411 bv2.Normalize()
412 bv2 *= scale
413 bv2 += cpt
414 return ((cpt, bv1), (cpt, bv2),), 'linear'
415