1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 """
26 Use MSMS to calculate surface info.
27
28 @note: This module is not any more the prefered module for
29 surface area calculations. SurfaceRacer is the default
30 module for this kind of calculations.
31 """
32
33 import Numeric as N
34 import Biskit.tools as T
35 import string
36 import os
37 import tempfile
38
39
40
41 from Biskit import Executor, TemplateError
42
43
44
46 pass
47
49 """
50 MSMS - pdb2xyzrn
51 ================
52
53 Run the awk script C{ pdb_to_xyzrn } to extract names and radii.
54 This is nessesary to run msms. The radii and atoms depend on where
55 in the sequence an atom resides. The radii used is determined
56 by the information in the C{ atomtypenumbers } file provided
57 with the MSMS application.
58
59 Result
60 ------
61 ::
62 r - atom radii array
63 n - atom name list
64 """
65
67 """
68 @param model: reference
69 @type model: PDBModel
70
71 @param kw: additional key=value parameters for Executor:
72 @type kw: key=value pairs
73 ::
74 debug - 0|1, keep all temporary files (default: 0)
75 verbose - 0|1, print progress messages to log (log != STDOUT)
76 node - str, host for calculation (None->local) NOT TESTED
77 (default: None)
78 nice - int, nice level (default: 0)
79 log - Biskit.LogFile, program log (None->STOUT) (default: None)
80
81 """
82 self.f_pdb = tempfile.mktemp('_pdb_to_xyzrn.pdb')
83
84
85
86
87 if os.path.exists( T.projectRoot() +'/external/msms/'):
88 dir = T.projectRoot() +'/external/msms/'
89 else:
90 raise pdb2xyzrnError_Error, 'Cannot find msms directory. This should reside in ~biskit/external/msms'
91
92 Executor.__init__( self, 'pdb2xyzrn', f_in=self.f_pdb,
93 cwd=dir, **kw )
94
95 self.model = model
96
97
99 """
100 Overrides Executor method.
101 """
102 self.model.writePdb( self.f_pdb )
103
104
110
111
113 """
114 Extract xyz and r from output.
115
116 @param output: STDOUT from pdb_to_xyzrn
117 @type output: [str]
118
119 @return: r, n - array with atom radii, list with atom names
120 @rtype: array, array
121 """
122 lines = output.split('\n')
123
124
125 xyzr = []
126 r = []
127 n = []
128
129 for l in lines:
130
131 if len(l)!=0:
132 l = string.split( l )
133 xyzr += [ float(l[0]), float(l[1]), \
134 float(l[2]), float(l[3]) ]
135 n += [ l[5] ]
136
137 xyzr = N.reshape( xyzr, ( len(xyzr)/4, 4 ) )
138
139 r = xyzr[:,3]
140
141
142 xyz = xyzr[:,:3]
143
144 return r, n
145
146
148 """
149 Overrides Executor method
150 """
151 return self.error is None
152
153
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
276 pass
277
278
279 -class MSMS( Executor ):
280 """
281 MSMS
282 ====
283
284 Calculate SAS (Solvent Accessible surface) and
285 SES (Solvent Excluded Surface) using the msms applicaton.
286
287 Run msms analytical surface calculation i.e.::
288 msms -if xyzr.coord -af atoms.area -surface ases
289
290 Result
291 ------
292 ::
293 out - dictionary - probe radii used, total SAS and SES
294 sesList - array of lenght atoms with SES (Solvent Excluded Surface)
295 sasList - array of lenght atoms with SAS (Solvent Accessible surface)
296
297 @note: The current default class for calculating MS and AS
298 is L{Biskit.SurfaceRacer}.
299 """
300
301
302 - def __init__( self, model, verbose=1, debug=1, **kw ):
303 """
304 @param model: PDBModel
305 @type model:
306
307 @param kw: additional key=value parameters for Executor:
308 @type kw: key=value pairs
309 ::
310 debug - 0|1, keep all temporary files (default: 0)
311 verbose - 0|1, print progress messages to log (log != STDOUT)
312 node - str, host for calculation (None->local) NOT TESTED
313 (default: None)
314 nice - int, nice level (default: 0)
315 log - Biskit.LogFile, program log (None->STOUT) (default: None)
316 """
317 self.f_xyzrn = tempfile.mktemp('_msms.xyzrn')
318
319
320 self.f_surf = tempfile.mktemp( )
321
322 arg =' -surface ases -if %s -af %s'%( self.f_xyzrn, self.f_surf )
323
324 Executor.__init__( self, 'msms', args=arg, **kw )
325
326 self.model = model.clone( deepcopy=1 )
327
328
330 """
331 Write a xyzrn coordinate file to disc.
332 Overrides Executor method.
333 """
334
335 p2x = pdb2xyzrn(self.model )
336 r, n = p2x.run()
337
338 xyz = self.model.xyz
339 xyzr = N.concatenate( ( xyz, N.transpose([r]) ) ,axis=1 )
340
341 f = open( self.f_xyzrn, 'w' )
342 i = 0
343 for line in xyzr:
344 f.write( str(line)[2:-1] + ' 1 ' + n[i] + '\n')
345 i += 1
346 f.close()
347
348
350 """
351 Remove temp files.
352 """
353 Executor.cleanup( self )
354
355 if not self.debug:
356 T.tryRemove( self.f_xyzrn )
357 T.tryRemove( self.f_surf + '.area' )
358
359
361 """
362 Parse the result file from a msms calculation.
363
364 @return: probe radii used, total SAS and SES,
365 array of lenght atoms with SES (Solvent Excluded Surface),
366 array of lenght atoms with SAS (Solvent Accessible surface),
367 and a list of atom names
368 @rtype: dict, array, array, [str]
369 """
370
371 out = string.split( open( self.f_out ).readlines()[-3] )
372 out = { 'probe':float(out[1]),
373 'ses':float(out[-2]),
374 'sas':float(out[-1]) }
375
376
377
378 surfName = self.f_surf + '.area'
379
380
381
382 outList = open( surfName , 'r').readlines()
383
384 sasList = []
385 sesList = []
386 atmList = []
387
388 for i in range( 1, len(outList) ):
389 line = string.split( outList[i] )
390
391 if len(line)== 4:
392 sesList += [ float( line[1] ) ]
393 sasList += [ float( line[2] ) ]
394 atmList += [ line[3] ]
395 else:
396 raise MSMS_Error, 'Wrong format in file %s'%surfName
397
398 return out, sesList, sasList, atmList
399
400
402 """
403 Overrides Executor method
404 """
405 return not self.error is None
406
407
414
415
416
417
418
419
420
422 """
423 Test class
424 """
425 from Biskit import PDBModel
426
427
428 - def run( self, local=0 ):
429 """
430 run function test
431
432 @param local: transfer local variables to global and perform
433 other tasks only when run locally
434 @type local: 1|0
435
436 @return: sum of SAS and SES areas
437 @rtype: float
438 """
439 from Biskit import PDBModel
440
441 if local: 'Loading PDB...'
442 m = PDBModel( T.testRoot() + '/lig/1A19.pdb' )
443 m = m.compress( m.maskProtein() )
444
445 if local: 'Getting surfaces via the MSMS executable'
446 ms = MSMS( m, debug=1, verbose=1 )
447
448 if local: 'Running'
449 out, sesList, sasList, atmList = ms.run()
450
451 if local:
452 print out
453 print '\nResult from MSMS (first 5 lines): '
454 print 'SES \tSAS \tAtom name'
455 for i in range(5):
456 print '%.2f \t%.2f \t%s'%(sesList[i], sasList[i], atmList[i])
457
458 print 'MSMS done'
459
460 globals().update( locals() )
461
462
463 return out['sas'] + out['ses']
464
465
467 """
468 Precalculated result to check for consistent performance.
469
470 @return: sum of SAS and SES areas
471 @rtype: float
472 """
473 return 5085.1580000000004 + 4208.7389999999996
474
475
476
477 if __name__ == '__main__':
478
479 test = Test()
480
481 assert abs( test.run( local=1 ) - test.expected_result() ) < 1e-8
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535