Package PyAutoDock :: Module scorer
[hide private]
[frames] | no frames]

Source Code for Module PyAutoDock.scorer

  1  ############################################################################ 
  2  # 
  3  # Authors: William Lindstrom, Ruth Huey 
  4  # 
  5  # Copyright: A. Olson TSRI 2004 
  6  # 
  7  ############################################################################# 
  8   
  9  # 
 10  # $Id: scorer.py,v 1.10 2007/06/13 23:42:19 gillet Exp $ 
 11  # 
 12   
 13   
 14  import math 
 15  from math import sqrt 
 16  import Numeric 
 17   
 18  from PyAutoDock.MolecularSystem import MolecularSystem 
 19   
 20   
21 -class ScoringStrategy:
22 """Abstract class 23 """
24 - def __init__(self, ms=None):
25 pass
26
27 - def set_molecular_system(self, ms):
28 """Abstract method 29 """ 30 raise NotImplementedError, "abstract method"
31
32 - def get_score(self):
33 """Abstract method 34 """ 35 raise NotImplementedError, "abstract method"
36 37 # ScoringStrategy 38 39
40 -class PairwiseScorer(ScoringStrategy):
41 - def __init__(self, ms=None):
42 ScoringStrategy.__init__(self, None) 43 if ms is not None: 44 self.set_molecular_system(ms) 45 46 self.required_attr_dictA = {} 47 self.required_attr_dictB = {}
48 49
50 - def set_molecular_system(self, ms):
51 """ 52 ms, a MolecularSystem, manages which of its entity_sets is 'receptor' 53 and which 'ligand' via its configuration tuple and 54 maintains the corresponding pairwise distance matrix. 55 56 'set_molecular_system' checks that the currently designated entity_sets have 57 attributes required by this scorer class (required_attr_dicts 58 manage only checking a required attr once per entity_sets.) 59 60 @@FIX THIS: if change ms configuration, reset required_attr_dicts 61 62 """ 63 # print "bases of ms", ms.__class__.__bases__ 64 # assert isinstance(ms, MolecularSystem) 65 66 # check the required attribute for both subsets before going on 67 listA = [] 68 for k,v in self.required_attr_dictA.items(): 69 if not v: 70 listA.append(k) 71 self.required_attr_dictA[k] = True 72 ms.check_required_attributes( ms.configuration[0], listA) 73 listB = [] 74 for k,v in self.required_attr_dictB.items(): 75 if not v: 76 listB.append(k) 77 self.required_attr_dictB[k] = True 78 ms.check_required_attributes( ms.configuration[1], listB) 79 80 # now set the molecular system 81 self.ms = ms
82
83 - def _f(self, at_a, at_b):
84 pass
85 86
87 - def get_score(self):
88 if self.ms is None: 89 raise RuntimeError("no molecular system available in scorer") 90 array = self.get_score_array() 91 return Numeric.add.reduce(Numeric.add.reduce(array))
92 93
94 - def get_score_array(self):
95 """return pairwise score 96 """ 97 # construct 2D array 98 array = [] 99 for at_a in self.ms.get_entities(self.ms.configuration[0]): 100 array.append([]) # a new row for every entity in first set 101 row = array[-1] 102 for at_b in self.ms.get_entities(self.ms.configuration[1]): 103 atom_score = self._f(at_a, at_b) 104 row.append(atom_score) 105 self.array = Numeric.array(array) 106 self.post_process() 107 return self.array
108
109 - def post_process(self):
110 pass
111 # PairwiseScorer 112 113 114
115 -class DistDepPairwiseScorer(PairwiseScorer):
116 non_bonded_cutoff = 8.0 # Angstroms 117
118 - def __init__(self, ms=None):
119 """constructor 120 """ 121 PairwiseScorer.__init__(self) 122 # add the required attributes of this subclass to the dict 123 self.required_attr_dictA.setdefault('coords', False) 124 self.required_attr_dictB.setdefault('coords', False) 125 if ms is not None: 126 self.set_molecular_system(ms) 127 128 self.use_non_bond_cutoff = True
129 130
131 - def _f(self, at_a, at_b, dist):
132 """distDepPairwise function stub 133 """ 134 return 1.0
135 136
137 - def get_score_array(self):
138 """return DistDepPairwise score 139 """ 140 entity_ix = self.ms.configuration[0] 141 entity_jx = self.ms.configuration[1] 142 distance = self.ms.get_dist_mat(entity_ix, entity_jx) 143 144 # construct 2D array 145 array = [] 146 cut = self.non_bonded_cutoff 147 if self.use_non_bond_cutoff==True: 148 for ax, at_a in enumerate(self.ms.get_entities(entity_ix)): 149 array.append([]) # a new row for every entity in first set 150 row = array[ax] # the 151 for bx, at_b in enumerate(self.ms.get_entities(entity_jx)): 152 d = distance[ax][bx] 153 atom_score = 0.0 154 # Obey non-bonded distance cutoff 155 if (d < cut): 156 atom_score = self._f(at_a, at_b, d) 157 row.append(atom_score) 158 else: # no cut_off 159 for ax, at_a in enumerate(self.ms.get_entities(entity_ix)): 160 array.append([]) # a new row for every entity in first set 161 row = array[ax] # the 162 for bx, at_b in enumerate(self.ms.get_entities(entity_jx)): 163 atom_score = self._f(at_a, at_b, distance[ax][bx] ) 164 row.append(atom_score) 165 self.array = Numeric.array(array) 166 self.post_process() 167 return self.array
168 # DistDepPairwiseScorer 169 170 171
172 -class WeightedMultiTerm(DistDepPairwiseScorer):
173 - def __init__(self):
174 DistDepPairwiseScorer.__init__(self) 175 self.terms = []
176 177
178 - def set_molecular_system(self, ms):
179 """ 180 ms, a MolecularSystem, manages which of its entity_sets is 'receptor' 181 and which 'ligand' via its configuration tuple and 182 maintains the corresponding pairwise distance matrix. 183 184 'set_molecular_system' checks that the currently designated entity_sets have 185 attributes required by this scorer class. (required_attr_dicts 186 manage only checking a required attr once per entity_sets.) 187 188 @@FIX THIS: if change ms configuration, reset required_attr_dicts 189 190 """ 191 # this call allows you to set the ms before any terms 192 # are added. when terms are added (see add_term) set_molecular_system 193 # will be called then. 194 DistDepPairwiseScorer.set_molecular_system(self, ms) 195 196 self.use_non_bond_cutoff = True 197 for term in self.terms: 198 term[0].set_molecular_system(self.ms)
199 200
201 - def add_term(self, term, weight=1.0):
202 """add the term and weight as a tuple to the list of terms. 203 """ 204 if hasattr(self, 'ms'): 205 term.set_molecular_system(self.ms) 206 self.terms.append( (term, weight) )
207 208
209 - def get_score(self):
210 score = 0.0 211 for term, weight in self.terms: 212 score = score + weight*term.get_score() 213 return score
214 215
216 - def get_score_per_term(self):
217 scorelist = [] 218 for term, weight in self.terms: 219 scorelist.append( weight*term.get_score() ) 220 return scorelist
221 222
223 - def get_score_array(self):
224 #weightedMultiTerm 225 t = self.terms[0] 226 # do you really want the list of arrays ? or a list of number for each 227 # scoring object? 228 array = t[0].get_score_array() * t[1] 229 if len(self.terms) > 1: 230 for term, weight in self.terms[1:]: 231 array = array + weight*term.get_score_array() 232 self.array = array 233 return self.array
234 # WeightedMultiTerm 235 236 237
238 -class Distance(PairwiseScorer):
239 """reference implementation of the Distance class 240 """
241 - def __init__(self, ms=None):
242 PairwiseScorer.__init__(self) 243 # add the required attributes of this subclass to the dict 244 self.required_attr_dictA.setdefault('coords', False) 245 self.required_attr_dictB.setdefault('coords', False) 246 if ms is not None: 247 self.set_molecular_system(ms)
248 249 250 #def _distance(self, a1, a2):
251 - def _f(self, at_a, at_b):
252 a1 = at_a.coords 253 a2 = at_b.coords 254 return math.sqrt( (a2[0]-a1[0])**2 + 255 (a2[1]-a1[1])**2 + 256 (a2[2]-a1[2])**2)
257 # Distance 258 259 260
261 -class HBondVDWSmoothing:
262 - def __init__(self, smooth_width=0.25):
263 # Autodock smooth default is 0.5 which is then 264 # divided by 2. before it's used 265 self.set_smooth_width(smooth_width)
266 267
268 - def set_smooth_width(self, smooth_width):
269 self.smooth_width = smooth_width # Angstoms
270 271
272 - def smooth_dist(self, dist, Rij,):
273 """Adjust atomic distance to effectively broaden energy well 274 275 dist is the distance between atoms 276 Rij is the distance at the energy well minimum 277 278 This implementation assumes that the energy function is 279 monotonicly decreasing between 0 and Rij and monotonicly 280 increasing for domain values greater than Rij 281 """ 282 width = self.smooth_width # amount to broaden energy well 283 284 # if dist is inside the "repulsive" side of the well 285 if dist < (Rij-width): 286 # move closer to energy well minimum 287 new_dist = dist + width 288 return new_dist 289 290 # if dist is beyond the "attractive" side of the well 291 if dist > (Rij + width): 292 # move closer to energy well minimum 293 new_dist = dist - width 294 return new_dist 295 296 # now dist is with-in width of Rij 297 return Rij
298 299 300 301 302 303 if __name__ == '__main__': 304 print "Tests are in Tests/test_scorer.py" 305 # test_scorer.run_test() 306