Package Biskit :: Module Xplorer
[hide private]
[frames] | no frames]

Source Code for Module Biskit.Xplorer

  1  ## 
  2  ## Biskit, a toolkit for the manipulation of macromolecular structures 
  3  ## Copyright (C) 2004-2005 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.5 $ 
 21  ## last $Date: 2006/12/21 09:33:09 $ 
 22  ## last $Author: leckner $ 
 23   
 24  """ 
 25  Prepare and run a xplor job. 
 26  """ 
 27   
 28  import tempfile 
 29  from time import time 
 30  import os 
 31   
 32  import settings 
 33  import Biskit.tools as t 
 34  from Biskit.Errors import BiskitError 
 35  from Biskit import StdLog 
 36   
37 -class XplorerError( BiskitError ):
38 pass
39
40 -class TemplateError( XplorerError ):
41 pass
42
43 -class RunError( XplorerError ):
44 pass
45
46 -class Xplorer:
47 """ 48 Prepare and run a xplor job 49 50 @todo: Most of this has been abstracted into Executor next thing 51 to do is to subclass Executor and delete redundant parts 52 """ 53
54 - def __init__( self, inpFile, xout=None, bin=settings.xplor_bin, 55 node=None, nice=0, log=None, debug=0, verbose=None, 56 **params ):
57 """ 58 @param inpFile: file name of inp template 59 @type inpFile: str 60 @param xout: file name of xplor log file (None->discard) 61 (default: None) 62 @type xout: str 63 @param bin: file name of xplor binary (default: settings.xplor_bin) 64 @type bin: str 65 @param node: host for calculation (None->local) (default: None) 66 @type node: str 67 @param nice: nice level (default: 0) 68 @type nice: int 69 @param log: Biskit.LogFile, program log (None->STOUT) (default: None) 70 @type log: str OR None 71 @param debug: keep all temporary files (default: 0) 72 @type debug: 0|1 73 @param verbose: print xplor command to log [log != STDOUT] 74 @type verbose: 0|1 75 @param params: additional key=value pairs for inp file 76 @type params: key=value 77 """ 78 self.__dict__.update( params ) 79 80 self.bin = t.absfile( bin ) or settings.xplor_bin 81 self.inp = t.absfile( inpFile ) 82 self.xout = t.absfile( xout ) or tempfile.mktemp('_xplor.log') 83 self.finp = None 84 self.node = node or os.uname()[1] ##.split('.')[0] 85 self.nice = nice 86 self.keepLog = xout is not None 87 self.debug = debug 88 89 ## Log object for own program messages 90 self.log = log or StdLog() 91 self.verbose = verbose 92 if self.verbose is None: 93 self.verbose = (log is not None) 94 95 ## time needed for last run 96 self.runTime = 0 97 98 ## version as of creation of this object 99 self.initVersion = self.version() 100 101 ## will contain Xplor log file after run finished 102 self.logLines = None
103 104
105 - def version( self ):
106 """ 107 Version of class. 108 109 @return: version 110 @rtype: str 111 """ 112 return 'Xplorer $Revision: 2.5 $'
113 114
115 - def runXplor( self, finp ):
116 """ 117 Run Xplor with given inp file and wait until it is finished. 118 Called by run(). 119 120 @param finp: name of existing input file (w/o place holders) 121 @type finp: str 122 123 @return: run time in s 124 @rtype: float 125 """ 126 start_time = time() 127 128 str_nice = "%s -%i" % (settings.nice_bin, self.nice) 129 130 lead_cmd = settings.ssh_bin 131 str_ssh = "%s %s" % ( settings.ssh_bin, self.node ) 132 133 cmd = "%s %s %s < %s > %s"\ 134 %(str_ssh, str_nice, self.bin, finp, self.xout) 135 136 if self.verbose: self.log.add_nobreak("executes: "+cmd+"..") 137 138 if os.spawnvp(os.P_WAIT, lead_cmd, cmd.split() ) <> 0: 139 raise RunError("non-0 exit status. \nCommand: "+cmd) 140 141 if self.verbose: self.log.add(".. finished.") 142 143 return time() - start_time
144 145
146 - def run( self, inp_mirror=None ):
147 """ 148 Run the callculation. This calls (in that order): 149 - L{ prepare() }, 150 - L{ runXplor() }, 151 - L{ parseLog() }, 152 - L{ finish() }/ L{ failed() }, 153 - L{ cleanup() } 154 155 @param inp_mirror: file name for formatted copy of inp file 156 (default: None) 157 @type inp_mirror: str 158 """ 159 160 self.prepare() 161 162 try: 163 inp = open( self.inp, 'r' ).read() 164 165 self.finp = inp_mirror or tempfile.mktemp('_xplor.inp') 166 167 self.generateInp( inp, self.finp ) 168 169 self.runTime = self.runXplor( self.finp ) 170 171 self.parseLog() 172 173 except RunError, why: 174 try: 175 self.failed() 176 finally: 177 self.cleanup() 178 raise RunError, why 179 180 try: 181 if self.isFailed(): 182 self.failed() 183 else: 184 self.finish() 185 finally: 186 self.cleanup()
187 188
189 - def cleanup( self ):
190 """ 191 Remove temporary files, override it but call it in the child 192 """ 193 if not self.keepLog and not self.debug: 194 t.tryRemove( self.xout ) 195 196 if not self.debug: 197 t.tryRemove( self.finp )
198 199
200 - def parseLog( self ):
201 """ 202 Parse xplor log into self.logLines 203 """ 204 self.logLines = open( self.xout ).readlines()
205 206
207 - def isFailed( self ):
208 """ 209 Calculation completion check. 210 211 @return: if xplor died 212 @rtype: 1 213 """ 214 return self.logLines == None or \ 215 self.logLines[-1].find("X-PLOR: exit time") == -1
216 217
218 - def prepare( self ):
219 """ 220 called before running xplor, override! 221 """ 222 pass
223 224
225 - def finish(self ):
226 """ 227 called after normal termination, override! 228 """ 229 pass
230 231
232 - def failed( self ):
233 """ 234 called after aborted calculation, override! 235 236 @raise RunError: if Xplor terminated with an error 237 """ 238 s = '' 239 try: 240 s += ''.join( self.logLines[-7:] ) 241 except: 242 pass 243 244 raise RunError, 'Xplor terminated with an error:\n' + s
245 246
247 - def generateInp(self, inp, fout):
248 """ 249 Replace formatstr place holders in inp by fields of this class. 250 251 @param inp: content of the input file with place holders 252 @type inp: str 253 @param fout: output file mane (xplor input file) 254 @type fout: str 255 256 @return: complete inp file 257 @rtype: str 258 259 @raise TemplateError: if unknown option/place holder in template file 260 @raise TemplateError: if error while creating template file 261 """ 262 try: 263 s = inp % self.__dict__ 264 f = open( fout, 'w') 265 f.write(s) 266 f.close() 267 268 except KeyError, why: 269 s = "Unknown option/place holder in template file." 270 s += "\n template file: " + self.inp 271 s += "\n Template asked for a option called " + str( why[0] ) 272 raise TemplateError, s 273 274 except Exception, why: 275 s = "Error while creating template file." 276 s += "\n template file: " + self.inp 277 s += "\n why: " + str( why ) 278 s += "\n Error:\n " + t.lastError() 279 raise TemplateError, s
280 281
282 - def saveXLog( self, fname ):
283 """ 284 Save the content of the XPlor log file to a new file. 285 286 @param fname: target file name 287 @type fname: str 288 289 @raise XPlorerError: if logLines is empty (Xplor hasn't been run) 290 """ 291 if not self.logLines: 292 raise XPlorerError('Xplor log file is (yet) empty.') 293 294 f = open( t.absfile(fname), 'w') 295 f.writelines( self.logLines ) 296 f.close()
297 298 299 300 ############# 301 ## TESTING 302 ############# 303
304 -class Test:
305 """ 306 Test class 307 """ 308 309 inp = """ 310 !! short test minimzation 311 312 ! ------------------------------------------------------------ 313 ! Place holders to be inserted by Python script 314 ! ------------------------------------------------------------ 315 evaluate ($ligandpsf = "%(lig_psf)s") 316 evaluate ($ligandpdb = "%(lig_pdb)s") 317 evaluate ($param19 = "%(param19)s" ) 318 evaluate ($lig_out = "%(lig_out)s" ) 319 320 ! ------------------------------------- 321 ! read psf and pdb files for the ligand 322 ! ------------------------------------- 323 structure @@$ligandpsf end 324 coor @@$ligandpdb 325 delete selection= (resname TIP3) end 326 327 ! ------------------ 328 ! set toplogies etc. 329 ! ------------------ 330 parameter 331 reset 332 @@$param19 333 end 334 335 ! ------------------------------------------------------------ 336 ! minimize 337 ! ------------------------------------------------------------ 338 flags exclude * include bond angle impr elec end 339 minimize powell nstep=10 end 340 341 ! --------------------------------------------------- 342 ! write minimized PDBs 343 ! --------------------------------------------------- 344 write coor output= $lig_out end 345 stop 346 """ 347
348 - def run( self, local=0 ):
349 """ 350 run function test 351 352 @param local: transfer local variables to global and perform 353 other tasks only when run locally 354 @type local: 1|0 355 356 @return: 357 @rtype: 358 """ 359 dir_out = tempfile.mkdtemp( '_test_Xplorer' ) 360 361 ## write a test template inp file to disc 362 f = open( dir_out +'/test.inp', 'w') 363 f.writelines( self.inp ) 364 f.close() 365 366 ## input template variables 367 param = t.projectRoot() + '/external/xplor/toppar/param19.pro' 368 pdb_out = dir_out +'/lig.pdb' 369 log_out = dir_out +'/test.out' 370 pdb_in = t.testRoot() + '/lig/1A19.pdb' 371 psf_in = t.testRoot() + '/lig/1A19.psf' 372 373 x = Xplorer( dir_out +'/test.inp', 374 xout = log_out, 375 verbose = local, 376 lig_psf = psf_in, 377 lig_pdb = pdb_in, 378 param19 = param, 379 lig_out = pdb_out ) 380 381 x.run() 382 383 if local: 384 print 'The minimized structure and the X-Plor log file has been written to %s and %s, respectively'%(pdb_out, log_out) 385 globals().update( locals() ) 386 387 return 1
388 389
390 - def expected_result( self ):
391 """ 392 Precalculated result to check for consistent performance. 393 394 @return: 395 @rtype: 396 """ 397 return 1
398 399 400 401 if __name__ == '__main__': 402 403 test = Test() 404 405 assert test.run( local=1 ) == test.expected_result() 406