Package Biskit :: Package Dock :: Module ComplexModelRegistry
[hide private]
[frames] | no frames]

Source Code for Module Biskit.Dock.ComplexModelRegistry

  1  ## 
  2  ## Biskit, a toolkit for the manipulation of macromolecular structures 
  3  ## Copyright (C) 2004-2006 Raik Gruenberg & Johan Leckner 
  4  ## 
  5  ## This program is free software; you can redistribute it and/or 
  6  ## modify it under the terms of the GNU General Public License as 
  7  ## published by the Free Software Foundation; either version 2 of the 
  8  ## License, or any later version. 
  9  ## 
 10  ## This program is distributed in the hope that it will be useful, 
 11  ## but WITHOUT ANY WARRANTY; without even the implied warranty of 
 12  ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
 13  ## General Public License for more details. 
 14  ## 
 15  ## You find a copy of the GNU General Public License in the file 
 16  ## license.txt along with this program; if not, write to the Free 
 17  ## Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
 18  ## 
 19  ## 
 20  ## $Revision: 2.13 $ 
 21  ## last $Date: 2007/04/06 10:16:08 $ 
 22  ## last $Author: graik $ 
 23   
 24  """ 
 25  This is a helper class for ComplexList. 
 26  """ 
 27   
 28  from Biskit.Dock import Complex 
 29  from Biskit.Errors import BiskitError 
 30  from Biskit import LocalPath, PDBModel 
 31   
 32  import Biskit.tools as T 
 33   
34 -class RegistryError( BiskitError ):
35 pass
36
37 -class ComplexModelRegistry:
38 """ 39 This is a helper class for ComplexList. 40 41 Keep unique copies of the rec and lig models from many Complexes. 42 Make sure that 2 Complexes with the same rec_model (same by file 43 name and unchanged) always point to the same PDBModel instance. 44 """ 45
46 - def __init__( self ):
47 48 self.rec_f2model = {} 49 self.lig_f2model = {} 50 51 self.rec_f2com = {} 52 self.lig_f2com = {} 53 54 self.initVersion = self.version()
55 56
57 - def version( self ):
58 """ 59 Version of class. 60 61 @return: version of class 62 @rtype: str 63 """ 64 return 'ComplexModelRegistry $Revision: 2.13 $'
65 66
67 - def addComplex( self, com ):
68 """ 69 Register Complex with the registry. 70 71 @param com: complex 72 @type com: Complex 73 """ 74 com.rec_model,fr = self.__sync_model( com.rec_model, self.rec_f2model ) 75 com.lig_model,fl = self.__sync_model( com.lig_model, self.lig_f2model ) 76 77 ## optimized for speed, that's why a bit awkward 78 if fr != None: 79 coms = self.rec_f2com.get( fr, None ) 80 if coms == None: 81 self.rec_f2com[ fr ] = [ com ] 82 else: 83 coms.append( com ) 84 85 if fl != None: 86 coms = self.lig_f2com.get( fl, None ) 87 if coms == None: 88 self.lig_f2com[ fl ] = [ com ] 89 else: 90 coms.append( com )
91 92
93 - def removeComplex( self, com ):
94 """ 95 Remove a Complex from the registry. 96 97 @param com: complex 98 @type com: Complex 99 """ 100 self.__removeModel(com.rec_model,com, self.rec_f2model, self.rec_f2com) 101 self.__removeModel(com.lig_model,com, self.lig_f2model, self.lig_f2com)
102 103
104 - def __removeModel( self, model, com, f2model, f2com ):
105 """ 106 Remove model of a complex from the registry. 107 108 @param model: receptor or ligand model 109 @type model: PDBModel 110 @param com: complex 111 @type com: Complex 112 @param f2model: dictionary mapping files to models 113 @type f2model: {str:PDBModel} 114 @param f2com: dictionary mapping files to complexes 115 @type f2com: {str:Complex} 116 """ 117 ## optimized for speed 118 f = model.source 119 coms = f2com[ f ] 120 coms.remove( com ) 121 122 if len( coms ) == 0: 123 del f2com[ f ] 124 del f2model[ f ]
125 126 127 ## def update( self, otherReg ): 128 ## """ 129 ## Add content of another registry to this one, make all 130 ## Complex.rec_model / lig_model to point to this Registry. 131 ## """ 132 ## ## currently not used 133 ## for k,v in otherReg.rec_f2model: 134 135 ## if not k in self.rec_f2model: 136 ## self.rec_f2model[ k ] = v 137 ## else: 138 139 ## m = self.rec_f2model[ k ] 140 141 ## if otherReg.rec_f2model != m: 142 ## for c in otherReg.rec_f2com[ k ]: 143 ## c.rec_model = m 144 145 ## for c in otherReg.rec_f2com[ k ]: 146 ## if not c in self.rec_f2com[ k ]: 147 ## self.rec_f2com[ k ] + [c] 148 149 ## for k,v in otherReg.lig_f2model: 150 151 ## if not k in self.lig_f2model: 152 ## self.lig_f2model[ k ] = v 153 154 ## else: 155 ## m = self.lig_f2model[ k ] 156 157 ## if otherReg.lig_f2model != m: 158 ## for c in otherReg.lig_f2com[ k ]: 159 ## c.lig_model = m 160 161 ## for c in otherReg.lig_f2com[ k ]: 162 ## if not c in self.lig_f2com[ k ]: 163 ## self.lig_f2com[ k ] + [c] 164 165
166 - def getRecModel( self, source ):
167 """ 168 Get receptor model belonging to source. 169 170 @param source: path 171 @type source: str 172 173 @return: model 174 @rtype: PDBModel 175 """ 176 return self.rec_f2model[source]
177 178
179 - def getLigModel( self, source ):
180 """ 181 Get ligand model belonging to source. 182 183 @param source: path 184 @type source: str 185 186 @return: model 187 @rtype: PDBModel 188 """ 189 return self.lig_f2model[source]
190 191
192 - def getModel( self, source):
193 """ 194 Get model belonging to source. 195 196 @param source: path 197 @type source: str 198 199 @return: model 200 @rtype: PDBModel 201 """ 202 if source in self.rec_f2model: 203 return self.rec_f2model[ source ] 204 205 return self.lig_f2model[ source ]
206 207
208 - def recModels( self ):
209 """ 210 Get a list with all receptor models. 211 212 @return: list of models 213 @rtype: [PDBModel] 214 """ 215 return self.rec_f2model.values()
216 217
218 - def ligModels( self ):
219 """ 220 Get a list with all ligand models. 221 222 @return: list of models 223 @rtype: [PDBModel] 224 """ 225 return self.lig_f2model.values()
226 227 228 ## def getSubRegistry( self, cl ): 229 ## """ 230 ## Get fraction of this Registry that is used by given list of 231 ## complexes. 232 ## cl - [ Complex ], all complexes must be part of the registry 233 ## -> ComplexModelRegistry 234 ## """ 235 ## if isinstance( cl, ComplexList ): 236 ## return cl.models 237 238 ## r = self.__class__() 239 240 ## for c in cl: 241 ## r.addComplex( c ) 242 243 ## return r 244 245
246 - def getRecComplexes( self, model ):
247 """ 248 Get the complexes of which a given receptor model is a component. 249 250 @param model: LocalPath or PDBModel 251 @type model: object 252 253 @return: list of Complexes 254 @rtype: [Complex] 255 """ 256 return self.__getComplexes( model, self.rec_f2com )
257 258
259 - def getLigComplexes( self, model ):
260 """ 261 Get the complexes of which a given ligand model is a component. 262 263 @param model: LocalPath or PDBModel 264 @type model: object 265 266 @return: list of Complexes 267 @rtype: [Complex] 268 """ 269 return self.__getComplexes( model, self.lig_f2com )
270 271
272 - def __getComplexes( self, model, f2com ):
273 """ 274 Get the complexes of which a given ligand model is a component. 275 276 @param model: LocalPath or PDBModel 277 @type model: object 278 @param f2com: dictionary mapping paths to complexes 279 @type f2com: {str:Complex} 280 281 @return: list of Complexes 282 @rtype: [Complex] 283 284 @raise RegistryError: if model has no source file. 285 """ 286 if isinstance( model, LocalPath): 287 f = model 288 289 try: 290 if isinstance( model, PDBModel ): 291 f = model.source 292 293 return f2com[ f ] 294 295 except KeyError, why: 296 raise RegistryError( "Model with source '%r' is unknown" % f )
297 298
299 - def __sync_model( self, m, f2model ):
300 """ 301 Get a shared model instance that is equal to m. If there is no such 302 instance in the registry, m is returned and m is added to the 303 registry - but only if it has been pickled to disc and hasn't 304 changed since. 305 306 @param m: PDBModel 307 @type m: PDBModel 308 @param f2model: dictionary with the path to the file as key 309 @type f2model: { str:PDBModel } 310 311 @return: Model from f2model equivalent to m, otherwise add m to f2model 312 and return m. File name or None for stray model 313 @rtype: PDBModel, str 314 """ 315 ## The problem here is to minimize the calls to PDBModel.validSource() 316 ## because 60.000 calls to os.path.exists() would take a lot of time 317 assert isinstance( m, PDBModel ) 318 319 if isinstance( m.source, LocalPath ): 320 f = m.source 321 else: 322 f = None 323 324 if f is not None: ## don't use "if f" because that would call f.__len__ 325 if m.xyzChanged: # or m.atomsChanged: 326 ## don't add it to registry, it will remain a stray model 327 return m, f 328 329 found = f2model.get( f, None ) 330 if found is not None: 331 ## the source has already been checked, we can skip the usual.. 332 ## .. exists() 333 return found, f 334 335 ## potentially new entry, check also whether the file exists 336 if m.source.exists(): 337 f2model[ f ] = m 338 339 return m, f
340 341
342 - def __str__( self ):
343 s = "Receptor models:" 344 for f in self.rec_f2model: 345 s += "\n%s: %i complexes" % \ 346 (f.formatted(), len( self.rec_f2com[ f ] ) ) 347 348 s += "\nLigand models:" 349 for f in self.lig_f2model: 350 s += "\n%s: %i complexes" % \ 351 (f.formatted(), len( self.lig_f2com[ f ] ) ) 352 353 return s
354 355
356 - def __repr__( self ):
357 return "ComplexModelRegistry\n" + self.__str__()
358 359 360 ############# 361 ## TESTING 362 ############# 363 import Biskit.test as BT 364
365 -class Test(BT.BiskitTest):
366 """Test case""" 367
369 """Dock.ComplexModelRegistry test""" 370 from Biskit.Dock import ComplexList 371 372 self.cl = T.Load( T.testRoot() +'/dock/hex/complexes.cl' ) 373 self.cl = self.cl.toList() 374 375 self.r = ComplexModelRegistry() 376 377 for c in self.cl[:500]: 378 self.r.addComplex( c ) 379 380 check = self.r.getLigComplexes( self.r.ligModels()[0] ) 381 382 self.assertEqual( len(check), 500 )
383 384 385 if __name__ == '__main__': 386 387 BT.localTest() 388