Home | Trees | Indices | Help |
|
---|
|
1 ## Automatically adapted for numpy.oldnumeric Mar 26, 2007 by alter_code1.py 2 3 ## 4 ## Biskit, a toolkit for the manipulation of macromolecular structures 5 ## Copyright (C) 2004-2006 Raik Gruenberg & Johan Leckner 6 ## 7 ## This program is free software; you can redistribute it and/or 8 ## modify it under the terms of the GNU General Public License as 9 ## published by the Free Software Foundation; either version 2 of the 10 ## License, or any later version. 11 ## 12 ## This program is distributed in the hope that it will be useful, 13 ## but WITHOUT ANY WARRANTY; without even the implied warranty of 14 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 ## General Public License for more details. 16 ## 17 ## You find a copy of the GNU General Public License in the file 18 ## license.txt along with this program; if not, write to the Free 19 ## Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 ## 21 ## 22 ## last $Date: 2007/03/26 18:40:42 $ 23 ## last $Author: graik $ 24 ## $Revision: 2.11 $ 25 26 """ 27 Calculate contact matrix and some scores for complexes. 28 """ 29 30 from Biskit.PVM import JobSlave 31 import Biskit.tools as T 32 from Biskit import mathUtils as MU 33 from Biskit.LogFile import StdLog, LogFile 34 import numpy.oldnumeric as N 35 from Complex import Complex 36 import os.path 37 import time 38 3940 -class ContactSlave(JobSlave):41 """ 42 Calculate contact matrix and some scores for complexes. 43 ContactMaster creates several instances of this class, each on one node. 44 """ 45470 471 472 import Biskit.test as BT 47347 """ 48 Version of Dock.Complex 49 50 @return: version of class 51 @rtype: str 52 """ 53 return 'ContactSlave $Revision: 2.11 $'54 5556 - def initialize(self, params):57 """ 58 Copy the parameters that ContactMaster is passing in as dict into 59 fields of this class. 60 61 @param params: defined in L{ContactMaster} 62 @type params: dict 63 """ 64 self.ferror = params['ferror'] 65 self.log = StdLog() 66 if params['log']: ## log to same file as master 67 self.log = LogFile( self.flog ) 68 self.verbose = params['verbose'] 69 70 ## reference complex data 71 self.c_ref_res_4_5 = self.c_ref_atom_4_5 = None 72 self.c_ref_atom_10 = None 73 self.mask_rec = self.mask_lig = None 74 self.mask_interface = self.mask_interface_bb = None 75 self.ref_interface_model = self.ref_interface_model_bb = None 76 77 ## reduced models and reduced reference contacts 78 self.reduced_recs = self.reduced_ligs = None 79 self.c_ref_ratom_10 = None 80 81 ## reference residue / atom contact matrices 82 if params.get( 'c_ref_res_4_5', None): 83 self.c_ref_res_4_5= MU.unpackBinaryMatrix(params['c_ref_res_4_5']) 84 85 self.c_ref_atom_4_5 = MU.unpackBinaryMatrix( 86 params['c_ref_atom_4_5']) 87 self.c_ref_atom_10 = MU.unpackBinaryMatrix( 88 params['c_ref_atom_10']) 89 90 ## atom masks for casting 91 if params.get('mask_rec', None): 92 self.mask_rec = MU.unpackBinaryMatrix( params['mask_rec'] ) 93 self.mask_lig = MU.unpackBinaryMatrix( params['mask_lig'] ) 94 95 ## for interface rms calculation 96 if params.get('mask_interface', None): 97 self.mask_interface = MU.unpackBinaryMatrix( 98 params['mask_interface']) 99 self.mask_interface_bb = MU.unpackBinaryMatrix( 100 params['mask_interface_bb'] ) 101 102 self.ref_interface_model = params['ref_interface_model'] 103 self.ref_interface_model_bb = params['ref_interface_model_bb'] 104 105 ## reduced rec and lig models indexed by source 106 self.reduced_recs = params['reduced_recs'] 107 self.reduced_ligs = params['reduced_ligs'] 108 109 if params.get( 'c_ref_ratom_10', None): 110 self.c_ref_ratom_10= MU.unpackBinaryMatrix( 111 params['c_ref_ratom_10']) 112 113 ## only calculate certain values 114 self.force = params.get('force', [] )115 116117 - def reportError(self, msg, soln ):118 """ 119 Report any errors to log 120 121 @param msg: error message 122 @type msg: str 123 @param soln: solution number for complex giving the error 124 @type soln: int 125 """ 126 try: 127 s = '%s on %s, soln %i\n' % (msg, os.uname()[1], soln) 128 s += '\t' + T.lastError() + '\n' 129 s += 'TraceBack: \n' + T.lastErrorTrace() + '\n' 130 f = open( self.ferror, 'a' ) 131 f.write( s ) 132 f.close() 133 except: 134 f = open('ErrorReportError_ContactSlave','a') 135 f.write('') 136 f.close()137 138139 - def __containsAny( self, lst_or_dic, *items ):140 """ 141 Check if dictionary or list contains items. 142 143 @param lst_or_dic: lokk for items in this 144 @type lst_or_dic: list OR dict 145 @param items: items to look for 146 @type items: any 147 148 @return: result of test 149 @rtype: 1|0 150 """ 151 for i in items: 152 if i in lst_or_dic: 153 return 1 154 return 0155 156158 """ 159 Determine the keys in an info dictionary of a complex that 160 need to be calculated or updated 161 162 @param c: Complex 163 @type c: Complex 164 @param keys: key or keys for c.infos dict 165 @type keys: str OR [str] 166 167 @return: 1 if the given value should be calculated for the 168 given complex 169 @rtype: 1|0 170 """ 171 ## force update 172 if self.force and self.__containsAny( self.force, *keys): 173 return 1 174 175 ## fill empty or nonexisting fields 176 for k in keys: 177 if not self.force and c.get(k, None) is None: 178 return 1 179 180 return 0181 182183 - def pickleError( self, o ):184 """ 185 Pickle object to disc. 186 187 @param o: object to pickle 188 @type o: any 189 """ 190 try: 191 fname = self.ferror + '_dat' 192 if not os.path.exists( fname ): 193 T.Dump( o, fname ) 194 except Exception, why: 195 f = open('ErrorReportError_ContactSlave','a') 196 f.write('Could not pickle error infos\n') 197 f.write( str( why ) ) 198 f.close()199 200201 - def calcContacts( self, soln, c ):202 """ 203 Calculate contact matrices and fraction of native contacts, residue- 204 and atom-based, with different distance cutoffs. 205 206 @param soln: solution number 207 @type soln: int 208 @param c: Complex 209 @type c: Complex 210 """ 211 try: 212 if self.requested(c, 'fnac_4.5') and self.c_ref_atom_4_5 != None: 213 ## cache pairwise atom distances for following calculations 214 contacts = c.atomContacts( 4.5, self.mask_rec, self.mask_lig, 215 cache=1, map_back=0 ) 216 ref = N.ravel( self.c_ref_atom_4_5 ) 217 218 c['fnac_4.5'] = N.sum( N.ravel(contacts) * ref )\ 219 / float( N.sum(ref)) 220 221 if self.requested(c, 'fnac_10') and self.c_ref_atom_10 != None: 222 223 contacts = c.atomContacts( 10., self.mask_rec, self.mask_lig, 224 cache=1, map_back=0 ) 225 226 ref = N.ravel( self.c_ref_atom_10 ) 227 c['fnac_10'] = N.sum( N.ravel(contacts) * ref ) \ 228 / float( N.sum(ref)) 229 230 if self.requested(c, 'c_res_4.5') \ 231 or ( self.c_ref_res_4_5 != None \ 232 and (self.requested(c,'fnrc_4.5','fnSurf_rec'))): 233 234 res_cont = c.resContacts( 4.5, 235 cache=self.requested(c, 'c_res_4.5')) 236 237 if self.c_ref_res_4_5 != None \ 238 and self.requested(c, 'fnrc_4.5' ): 239 ref = N.ravel( self.c_ref_res_4_5 ) 240 c['fnrc_4.5'] = N.sum(N.ravel(res_cont)*ref) \ 241 /float(N.sum(ref)) 242 243 if self.c_ref_res_4_5 != None \ 244 and self.requested(c, 'fnSurf_rec'): 245 r, l = c.fractionNativeSurface(res_cont, 246 self.c_ref_res_4_5 ) 247 c['fnSurf_rec'] = r 248 c['fnSurf_lig'] = l 249 250 except: 251 m1 = m2 = s = 0 252 try: 253 m1, m2, s = c.get('model1',0), c.get('model2',0),\ 254 c.get('soln',0) 255 except: 256 pass 257 self.reportError('contact error (r %i : l %i, #%i)'%\ 258 (m1,m2,s), soln)259 ## self.pickleError( {'com':c, 'mrec':self.mask_rec, 260 ## 'mlig':self.mask_lig } ) 261 262263 - def calcReducedContacts( self, soln, c ):264 """ 265 Get contact matrices and/or fnarc from reduced-atom models. 266 267 @param soln: solution number 268 @type soln: int 269 @param c: Complex 270 @type c: Complex 271 """ 272 if not (self.reduced_recs and self.reduced_ligs): 273 return 274 275 if not self.requested(c,'c_ratom_10','fnarc_10'): 276 return 277 278 try: 279 ## create Complex with same orientation but reduced coordinates 280 red_rec = self.reduced_recs[ c.rec_model.source ] 281 red_lig = self.reduced_ligs[ c.lig_model.source ] 282 red_com = Complex( red_rec, red_lig, c.ligandMatrix ) 283 284 contacts = red_com.atomContacts( 10.0, cache=1 ) 285 286 if self.requested(c, 'c_ratom_10'): 287 c['c_ratom_10'] = MU.packBinaryMatrix(contacts) 288 289 if self.c_ref_ratom_10 is not None: 290 ref = N.ravel( self.c_ref_ratom_10 ) 291 c['fnarc_10'] = N.sum( N.ravel(contacts) * ref )\ 292 / float( N.sum(ref)) 293 294 except: 295 self.reportError('reduced contacts error', soln)296 ## self.pickleError({'com':c, 'red_recs':self.reduced_recs, 297 ## 'red_ligs':self.reduced_ligs}) 298 299300 - def calcInterfaceRms( self, soln, c ):301 """ 302 RMS between this and reference interface atoms after superposition. 303 - rms_if_bb, considers backbone of interface residues (10 A cutoff) 304 (same as used for CAPRI) 305 - rms_if, considers all atoms of more tightly defined interf. 306 residues (correlates better with fraction of native contacts) 307 308 @param soln: solution number 309 @type soln: int 310 @param c: Complex 311 @type c: Complex 312 """ 313 try: 314 if self.requested(c, 'rms_if_bb') and self.ref_interface_model_bb: 315 316 m = c.model().compress(self.mask_interface_bb) 317 c['rms_if_bb'] = self.ref_interface_model_bb.rms( m ) 318 319 if self.requested(c, 'rms_if') and self.ref_interface_model: 320 321 m = c.model().compress( self.mask_interface ) 322 c['rms_if'] = self.ref_interface_model.rms( m ) 323 324 except: 325 self.reportError('interface rms error', soln)326 327 328 ## def calcProsa( self, soln, c ): 329 ## """ProsaII energy score""" 330 ## if self.requested( c, 'eProsa'): 331 ## try: 332 ## prosaE = c.prosaEnergy() 333 ## c['eProsa'] = prosaE 334 ## except: 335 ## self.reportError('Prosa Error', soln ) 336 ## c['eProsa'] = None 337 338340 """ 341 Prosa2003 energy score 342 343 @param soln: solution number 344 @type soln: int 345 @param c: Complex 346 @type c: Complex 347 """ 348 # import socket 349 if self.requested( c, 'eProsa'): 350 try: 351 prosaE = c.prosa2003Energy() 352 c['eProsa'] = prosaE 353 except: 354 c['eProsa'] = None 355 # c['eProsa'] = socket.gethostname() 356 self.reportError('Prosa Error', soln )357 358359 - def calcPairScore( self, soln, c ):360 """ 361 calculate contact pair score 362 363 @param soln: solution number 364 @type soln: int 365 @param c: Complex 366 @type c: Complex 367 """ 368 if self.requested( c,'ePairScore'): 369 try: 370 pairScore = c.contPairScore(cutoff=6.0, log=self.log, 371 verbose=self.verbose ) 372 c['ePairScore'] = pairScore 373 except: 374 c['ePairScore'] = None 375 self.reportError('PairScore Error', soln )376 377378 - def calcConservation( self, soln, c, method ):379 """ 380 calculate conservation score 381 382 @param soln: solution number 383 @type soln: int 384 @param c: Complex 385 @type c: Complex 386 @param method: scoring method to use see L{Complex.conservationScore} 387 @type method: str 388 """ 389 if self.requested( c, method): 390 try: 391 c[method] = c.conservationScore( method, log=self.log, 392 verbose=self.verbose ) 393 except: 394 self.reportError('Conservation score Error', soln)395 396398 """ 399 calculate fold-X binding energies 400 401 @param soln: solution number 402 @type soln: int 403 @param c: Complex 404 @type c: Complex 405 """ 406 if self.requested( c, 'foldX' ): 407 try: 408 c['foldX'] = c.foldXEnergy() 409 except: 410 self.reportError('FoldX Error', soln)411 412414 """ 415 Obtain contact matrix for all complexes. 416 417 @param cmplxDic: dictionary of complexes:: 418 {soln:Complex, soln:Complex, ...} 419 @type cmplxDic: {int:Complex} 420 421 @return: similar dictionary with Complex.info['soln'] as keys and 422 file names of matrices as value:: 423 { soln : fname, soln : fname ....} 424 @rtype: {int:str} 425 426 """ 427 result = {} 428 429 startTime = time.time() 430 431 for soln, c in cmplxDic.items(): 432 T.flushPrint( "%i," % soln ) 433 434 ## if not os.path.exists( T.absfile('~/debug.dic') ): 435 ## T.Dump( cmplxDic, T.absfile('~/debug.dic') ) 436 437 self.calcContacts( soln, c ) 438 439 self.calcInterfaceRms( soln, c ) 440 441 self.calcReducedContacts( soln, c ) 442 443 ## TODO: Prosa will not run when called via conatacSlave, runs as it should when 444 ## called as c.prosa2003Energy() in the interpreter. What's wroong here? 445 ## For mow the Prosa calculation is skipped. 446 ## 447 self.calcProsa( soln, c ) 448 449 self.calcPairScore( soln, c ) ## uses res-contacts 450 451 self.calcFoldX( soln, c ) ##uses rec/lig.info['foldX'] if available 452 453 for method in ['cons_ent', 'cons_max', 'cons_abs']: 454 self.calcConservation( soln, c, method ) 455 456 c['__version_contacter'] = self.version() 457 458 result[ soln ] = c 459 460 c.slim() 461 462 ## if not os.path.exists(T.absfile('~/debug_afterslave.dic') ): 463 ## T.Dump( cmplxDic, T.absfile('~/debug_afterslave.dic') ) 464 465 466 print "\navg time for last %i complexes: %f s" %\ 467 ( len(cmplxDic), (time.time()-startTime)/len(cmplxDic)) 468 469 return result475 """Test ContactSlave locally without running the master. 476 477 This allows to test the master and slave without using 478 external nodes. The master still requires a running PVM 479 though. 480 """ 481 482 TAGS = [ BT.PVM ] 483529 530 ## ## PROFILING: 531 ## in slave window: 532 ## slave.stop() 533 ## import profile 534 ## profile.run( 'slave._go( slave.dic )', 'report.out' ) 535 536 ## ## Analyzing 537 ## import pstats 538 ## p = pstats.Stats('report.out') 539 540 ## ## long steps and methods calling them 541 ## p.sort_stats('cumulative').print_stats(20) 542 ## p.print_callers(0.1) 543 544 ## ## time consuming methods 545 ## p.sort_stats('time').print_stats(10) 546 547 548 if __name__ == '__main__': 549 550 ## BT.localTest() 551 552 import os, sys 553 554 if len(sys.argv) == 2: 555 556 niceness = int(sys.argv[1]) 557 os.nice(niceness) 558 559 slave = ContactSlave() 560 slave.start() 561485 import tempfile 486 self.cl_out = tempfile.mktemp('_test.cl')487488 - def test_ContactSlave(self):489 """Dock.ContactSlave test (local)""" 490 import os 491 from Biskit.Dock.ContactMaster import ContactMaster 492 493 ## load complex list (docking result) and reference complex 494 lst = T.Load( T.testRoot() + "/dock/hex/complexes.cl") 495 lst = lst[:3] 496 refcom = T.Load( T.testRoot() + "/com/ref.complex") 497 498 ## let ContactMaster prepare everything but don't run it 499 self.master = ContactMaster( lst, verbose = self.local, 500 log=self.log, 501 refComplex = refcom, 502 outFile = self.cl_out ) 503 504 jobs = self.master.data 505 506 self.slave = ContactSlave() 507 self.slave.initialize( self.master.getInitParameters(1) ) 508 509 if self.local or self.VERBOSITY > 2: 510 self.log.writeln("Currently available info records (from hex):") 511 self.log.writeln( repr(jobs[0].info.keys()) ) 512 self.log.writeln( "Calculating all scores for %i complexes..." \ 513 % len(jobs) ) 514 515 self.result = self.slave.go( jobs ) 516 517 if self.local or self.VERBOSITY > 2: 518 self.log.writeln("info records after contacting: ") 519 self.log.writeln( repr(jobs[0].info.keys()) ) 520 if self.local: 521 print "new scores are available in 'result[0-2].info'" 522 523 ## verify fraction of native atom contacts for third complex 524 self.assertAlmostEqual( self.result[2]['fnac_10'], 525 0.11533600168527491, 7 )526528 T.tryRemove( self.cl_out )
Home | Trees | Indices | Help |
|
---|
Generated by Epydoc 3.0alpha3 on Tue May 1 22:35:06 2007 | http://epydoc.sourceforge.net |