1
2
3
4
5
6
7
8
9
10
11 from rdkit import Geometry
12 from rdkit.Chem import ChemicalFeatures
13 from rdkit.Chem.FeatMaps import FeatMaps,FeatMapPoint
14 import re
15
16 """
17
18 ScoreMode=All
19 DirScoreMode=Ignore
20
21 BeginParams
22 family=Aromatic radius=2.5 width=1.0 profile=Gaussian
23 family=Acceptor radius=1.5
24 EndParams
25
26 # optional
27 BeginPoints
28 family=Acceptor pos=(1.0, 0.0, 5.0) weight=1.25 dir=(1, 1, 0)
29 family=Aromatic pos=(0.0,1.0,0.0) weight=2.0 dir=(0,0,1) dir=(0,0,-1)
30 family=Acceptor pos=(1.0,1.0,2.0) weight=1.25
31 EndPoints
32
33 """
34
37
39 data=None
46
48 if isinstance(data,str):
49 self.data=data.split('\n')
50 else:
51 self.data=data
52 self._lineNum=0
53
55 txt = ''
56 while 1:
57 try:
58 l = self.data[self._lineNum].split('#')[0].strip()
59 except IndexError:
60 break
61 self._lineNum+=1
62 if l:
63 txt += l
64 if l[-1]!='\\':
65 break
66 return txt
67
68 - def Parse(self,featMap=None):
102
104 paramLineSplitter = re.compile(r'([a-zA-Z]+) *= *(\S+)')
105 params = {}
106
107 l = self._NextLine()
108 while l and l!='EndParams':
109 param = FeatMaps.FeatMapParams()
110 vals=paramLineSplitter.findall(l)
111 for name,val in vals:
112 name = name.lower()
113 if name=='family':
114 family=val
115 elif name=='radius':
116 param.radius=float(val)
117 elif name=='width':
118 param.width=float(val)
119 elif name=='profile':
120 try:
121 param.featProfile=getattr(param.FeatProfile,val)
122 except AttributeError:
123 raise FeatMapParseError('Profile %s not recognized on line %d'%(val,self._lineNum))
124 else:
125 raise FeatMapParseError('FeatMapParam option %s not recognized on line %d'%(name,self._lineNum))
126 params[family]=param
127 l = self._NextLine()
128
129 if l!='EndParams':
130 raise FeatMapParseError('EndParams line not found')
131
132 return params
133
135 txt = txt.strip()
136 startP=0
137 endP=len(txt)
138 if txt[0]=='(':
139 startP += 1
140 if txt[-1]==')':
141 endP -= 1
142 txt = txt[startP:endP]
143 splitL = txt.split(',')
144 if len(splitL) != 3:
145 raise ValueError('Bad location string')
146 vs = [float(x) for x in splitL]
147 pt = Geometry.Point3D(vs[0],vs[1],vs[2])
148 return pt
149
150
152 featLineSplitter = re.compile(r'([a-zA-Z]+) *= *')
153 feats = []
154
155 l = self._NextLine()
156 while l and l!='EndPoints':
157 vals=featLineSplitter.split(l)
158 while vals.count(''): vals.remove('')
159 p = FeatMapPoint.FeatMapPoint()
160
161 i=0
162 while i<len(vals):
163 name = vals[i].lower()
164 if name=='family':
165 i+=1
166 val = vals[i].strip()
167 p.SetFamily(val)
168 elif name=='weight':
169 i+=1
170 val = float(vals[i])
171 p.weight = val
172 elif name=='pos':
173 i+=1
174 val = vals[i]
175 pos = self._parsePoint(val)
176 p.SetPos(pos)
177 elif name=='dir':
178 i+=1
179 val = vals[i]
180 pos = self._parsePoint(val)
181 p.featDirs.append(pos)
182 else:
183 raise FeatMapParseError('FeatPoint option %s not recognized on line %d'%(name,self._lineNum))
184 i+=1
185 feats.append(p)
186 l = self._NextLine()
187 return feats
188
189
190
191
193 import doctest,sys
194 return doctest.testmod(sys.modules["__main__"])
195
196 if __name__ == '__main__':
197 import sys
198 failed,tried = _test()
199 sys.exit(failed)
200