1
2
3
4
5
6
7
8
9
10
11 from rdkit import Geometry
12 from rdkit import Chem
13 from rdkit.Chem import ChemicalFeatures
14 from rdkit.Chem.FeatMaps.FeatMapPoint import FeatMapPoint
15 import math
16
18 All=0
19 """ score each feature in the probe against every matching
20 feature in the FeatMap.
21 """
22
23 Closest=1
24 """ score each feature in the probe against the closest
25 matching feature in the FeatMap.
26 """
27
28 Best=2
29 """ score each feature in the probe against the matching
30 feature in the FeatMap that leads to the highest score
31 """
32
34 Ignore=0
35 """ ignore feature directions
36 """
37
38 DotFullRange=1
39 """ Use the dot product and allow negative contributions when
40 directions are anti-parallel.
41 e.g. score = dot(f1Dir,f2Dir)
42 """
43
44 DotPosRange=2
45 """ Use the dot product and scale contributions to lie between
46 zero and one.
47 e.g. score = ( dot(f1Dir,f2Dir) + 1 ) / 2
48 """
49
51 """ one of these should be instantiated for each
52 feature type in the feature map
53 """
54 radius=2.5
55 " cutoff radius "
56
57 width=1.0
58 " width parameter (e.g. the gaussian sigma) "
59
65
66 featProfile=FeatProfile.Gaussian
67
69 dirScoreMode = FeatDirScoreMode.Ignore
70 scoreMode=FeatMapScoreMode.All
71 params = {}
72 - def __init__(self,params=None,feats=None,
73 weights=None):
77
79 self._feats = []
80 if feats:
81 if len(feats)!=len(weights):
82 raise ValueError('feats and weights lists must be the same length')
83 for feat,weight in zip(feats,weights):
84 self.AddFeature(feat,weight)
85
95
97 if not isinstance(featPt,FeatMapPoint):
98 raise ValueError('addFeatPoint() must be called with a FeatMapPoint instance')
99 if self.params and not featPt.GetFamily() in self.params:
100 raise ValueError('feature family %s not found in params'%featPt.GetFamily())
101 self._feats.append(featPt)
102
103
106
108 return len(self._feats)
109
111 return self._feats[i]
112
115
117 for sIdx,sFeat in enumerate(self._feats):
118 if sFeat.GetFamily()==oFeat.GetFamily():
119 yield sIdx,sFeat
120
156
157 - def ScoreFeats(self,featsToScore,mapScoreVect=[],featsScoreVect=[],
158 featsToFeatMapIdx=[]):
159 nFeats = len(self._feats)
160 if mapScoreVect and len(mapScoreVect)!=nFeats:
161 raise ValueError('if provided, len(mapScoreVect) should equal numFeats')
162 nToScore = len(featsToScore)
163 if featsScoreVect and len(featsScoreVect)!=nToScore:
164 raise ValueError('if provided, len(featsScoreVect) should equal len(featsToScore)')
165 if featsToFeatMapIdx and len(featsToFeatMapIdx)!=nToScore:
166 raise ValueError('if provided, len(featsToFeatMapIdx) should equal len(featsToScore)')
167
168 if mapScoreVect:
169 for i in range(nFeats): mapScoreVect[i]=0.0
170 else:
171 mapScoreVect = [0.0]*nFeats
172
173 if self.scoreMode==FeatMapScoreMode.Closest:
174 defScore=1000.0
175 else:
176 defScore=0.0
177 if featsScoreVect:
178 for i in range(nToScore): featsScoreVect[i]=defScore
179 else:
180 featsScoreVect = [defScore]*nToScore
181
182 if not featsToFeatMapIdx:
183 featsToFeatMapIdx = [None]*nToScore
184
185 for i in range(nToScore):
186 if self.scoreMode != FeatMapScoreMode.All:
187 featsToFeatMapIdx[i]=[-1]
188 else:
189 featsToFeatMapIdx[i]=[]
190
191 for oIdx,oFeat in enumerate(featsToScore):
192 for sIdx,sFeat in self._loopOverMatchingFeats(oFeat):
193 if self.scoreMode == FeatMapScoreMode.Closest:
194 d = sFeat.GetDist2(oFeat)
195 if d<featsScoreVect[oIdx]:
196 featsScoreVect[oIdx]=d
197 featsToFeatMapIdx[oIdx][0]=sIdx
198 else:
199 lScore = self.GetFeatFeatScore(sFeat,oFeat,typeMatch=False)
200 if self.scoreMode == FeatMapScoreMode.Best:
201 if lScore>featsScoreVect[oIdx]:
202 featsScoreVect[oIdx]=lScore
203 featsToFeatMapIdx[oIdx][0]=sIdx
204 elif self.scoreMode == FeatMapScoreMode.All:
205 featsScoreVect[oIdx] += lScore
206 mapScoreVect[sIdx] += lScore
207 featsToFeatMapIdx[oIdx].append(sIdx)
208 else:
209 raise ValueError('bad score mode')
210
211 totScore = 0.0
212 if self.scoreMode == FeatMapScoreMode.Closest:
213 for oIdx,oFeat in enumerate(featsToScore):
214 sIdx = featsToFeatMapIdx[oIdx][0]
215 if sIdx>-1:
216 lScore = self.GetFeatFeatScore(sFeat,oFeat,typeMatch=False)
217 featsScoreVect[oIdx] = lScore
218 mapScoreVect[sIdx] = lScore
219 totScore += lScore
220 else:
221 featsScoreVect[oIdx] = 0
222
223 else:
224 totScore = sum(featsScoreVect)
225 if self.scoreMode == FeatMapScoreMode.Best:
226 for oIdx,lScore in enumerate(featsScoreVect):
227 sIdx = featsToFeatMapIdx[oIdx][0]
228 if sIdx>-1:
229 mapScoreVect[sIdx]=lScore
230
231
232 if self.scoreMode != FeatMapScoreMode.All:
233 for elem in featsToFeatMapIdx:
234 if elem==[-1]:
235 elem.pop()
236 return totScore
237
238
240 res = ''
241 for i,feat in enumerate(self._feats):
242 weight = feat.weight
243 pos = feat.GetPos()
244 res += '% 3d % 12s % 6.4f % 6.4f % 6.4f % 6.4f\n'%(i+1,
245 feat.GetFamily(),
246 pos.x,pos.y,pos.z,weight)
247 return res
248
249
250
251
252
253
255 import doctest,sys
256 return doctest.testmod(sys.modules["__main__"])
257
258 if __name__ == '__main__':
259 import sys
260 failed,tried = _test()
261 sys.exit(failed)
262